TypeScript Deep Dive 日本語版
  • TypeScript Deep Dive 日本語版
  • TypeScript入門 & 環境構築
    • なぜTypeScriptを使うのか?
  • JavaScript
    • 等価演算子の同一性
    • リファレンス
    • nullとundefined
    • this
    • クロージャ
    • Number型
    • Truthy
  • モダンなJavaScriptの機能
    • クラス
      • Classes Emit
    • アロー関数
    • 残余引数(Restパラメータ)
    • let
    • const
    • 分割代入
    • スプレッド演算子
    • for...of
    • Iterator
    • テンプレートリテラル
    • Promise
    • ジェネレータ
    • async await
  • プロジェクトの環境設定
    • コンパイルコンテキスト
      • tsconfig.json
      • コンパイル対象ファイルの設定
    • 宣言空間
    • ファイルモジュール
      • ファイルモジュールの詳細
      • global.d.ts
    • 名前空間
    • 動的インポート
  • Node.js & TypeScriptのプロジェクト作成
  • React & TypeScriptのプロジェクト作成
  • TypeScriptの型システム
    • JavaScriptからの移行ガイド
    • @types パッケージ (DefinitelyTyped)
    • アンビエント宣言(declare)
      • 型定義ファイル
      • グローバル変数の宣言
    • インターフェース
    • Enum
    • lib.d.ts
    • 関数の型
    • 呼び出し可能オブジェクト
    • Type Assertion(型アサーション)
    • Freshness
    • 型ガード
    • リテラル型
    • Readonly
    • ジェネリック型
    • 型推論
    • 型の互換性
    • never
    • 判別可能なUnion型
    • Index signature(インデックス型)
    • 型の移動
    • 例外のハンドリング
    • ミックスイン
  • JSX
    • React
    • React以外のJSX
  • オプション
    • noImplicitAny
    • strictNullChecks
  • TypeScriptのエラー
    • エラーの理解
    • 一般的なエラー
  • NPM
  • テスト
    • Jest
    • Cypress
  • ツール
    • Prettier
    • Husky
    • Changelog
  • その他のヒント
    • String Based Enums
    • Nominal Typing
    • Stateful Functions
    • Bind is Bad
    • Currying
    • Type Instantiation
    • Lazy Object Literal Initialization
    • Classes are Useful
    • Avoid Export Default
    • Limit Property Setters
    • outFile caution
    • JQuery tips
    • static constructors
    • singleton pattern
    • Function parameters
    • Build Toggles
    • Barrel
    • Create Arrays
    • Typesafe Event Emitter
  • スタイルガイド(コーディング規約)
  • TypeScriptコンパイラの内側
    • Program
    • AST
      • TIP: Visit Children
      • TIP: SyntaxKind enum
      • Trivia
    • Scanner
    • Parser
      • Parser Functions
    • Binder
      • Binder Functions
      • Binder Declarations
      • Binder Container
      • Binder SymbolTable
      • Binder Error Reporting
    • Checker
      • Checker Diagnostics
      • Checker Error Reporting
    • Emitter
      • Emitter Functions
      • Emitter SourceMaps
    • Contributing
GitBook提供
このページ内
  • セットアップ
  • HTMLタグ vs Component
  • 型チェック(Type Checking)
  • HTMLタグ
  • Functionコンポーネント(Functional Components)
  • クラスコンポーネント(Class Components)
  • React JSX のヒント: レンダリング可能なインターフェース
  • React JSX のヒント:コンポーネントのインスタンスを受け入れる
  • React JSXのヒント: propsを受け取り、JSXでレンダリングできるコンポーネントを受け入れる
  • React JSXのヒント: ジェネリックコンポーネント
  • ジェネリック関数
  • Reactのヒント: 厳密に型付けされたRef
  • 型アサーション
  • デフォルトProps
  • WebComponentの宣言

役に立ちましたか?

  1. JSX

React

前へJSX次へReact以外のJSX

最終更新 2 年前

役に立ちましたか?

セットアップ

。要点をまとめると、次の通りです。

  • ファイル拡張子.tsx(.tsの代わりに)を使用してください。

  • tsconfig.jsonのcompilerOptionsで "jsx" : "react"を使ってください。

  • JSXとReactの定義をあなたのプロジェクトにインストールします:(npm i -D @types/react @types/react-dom)。

  • reactを.tsxファイルにインポートします(import React from "react"となります)。

ReactとTypeScriptのプロジェクトをセットアップする一番簡単な方法は、を使うことです。このツールはReactチームから提供されているツールです。公式にTypeScriptのテンプレートが提供されています。Create React Appを使うには、$ npm i -g create-react-appというコマンドでローカルPCにグローバルにインストールできます。そうすれば、に書かれているように$ npx create-react-app my-app --template typescriptというコマンドで、最初からTypeScriptを利用可能なプロジェクトを簡単に作成できます。

HTMLタグ vs Component

Reactは、HTMLタグ(文字列)または、React Component(クラス)を表示できます。これらのJavaScriptへのコンパイル結果は同じではありません(例えば、、React.createElement('div')とReact.createElement(MyComponent)のJavaScriptのコンパイル結果に同じではありません)。どちらとして扱われるかは、最初の文字の_ケース_(大文字小文字)です。fooはHTMLタグとして扱われます。そして、Fooはコンポーネントとして扱われます。

型チェック(Type Checking)

HTMLタグ

HTMLタグfooの型はJSX.IntrinsicElements.fooです。これらの主要な型は、セットアップの一部としてインストールした型定義ファイルreact-jsx.d.tsの中で、予め定義されています。下記にその中に含まれる型定義のサンプルを示します。

declare module JSX {
    interface IntrinsicElements {
        a: React.HTMLAttributes;
        abbr: React.HTMLAttributes;
        div: React.HTMLAttributes;
        span: React.HTMLAttributes;

        /// などなど
    }
}

Functionコンポーネント(Functional Components)

単にReact.FCインターフェースを使ってステートレスなFunctionコンポーネントを定義することができます。React.FCは単に、React.FunctionComponentの短いバージョンです。

type Props = {
  foo: string;
}
const MyComponent: React.FC<Props> = (props) => {
    return <span>{props.foo}</span>
}

<MyComponent foo="bar" />

クラスコンポーネント(Class Components)

コンポーネントは、propsプロパティに基づいて型チェックされます。コンポーネントは、JSXが、どのように変換されるか、ということを考慮して型チェックされます。例えばJSXのタグの属性は、コンポーネントのpropsの一部である必要があります。

Reactのステートフルなコンポーネントを作成するには、クラスを使用します。型定義ファイルreact.d.tsは、React.Component<Props,State>クラスを定義しています。このクラスを、コンポーネントを作成するときに継承します。このクラスは、そのコンポーネント独自のPropsとStateの型をジェネリクスとして設定できるようになっています。これを以下の例で示します(下記の例では、Stateには空のオブジェクト型を設定しています):

type Props = {
  foo: string;
}
class MyComponent extends React.Component<Props, {}> {
    render() {
        return <span>{this.props.foo}</span>
    }
}

<MyComponent foo="bar" />

React JSX のヒント: レンダリング可能なインターフェース

ReactはJSXやstringをレンダリングすることができます。これらはすべてReact.ReactNode型に統合されていますので、レンダリング可能なものを受け入れる場合などに使用してください。

type Props = {
  header: React.ReactNode;
  body: React.ReactNode;
}
class MyComponent extends React.Component<Props, {}> {
    render() {
        return <div>
            {this.props.header}
            {this.props.body}
        </div>;
    }
}

<MyComponent header="これはヘッダーです" body="これはボディです" />

React JSX のヒント:コンポーネントのインスタンスを受け入れる

Reactの型定義ファイルは、React.ReactElement<T>という型を提供しています。これを、<T/>クラスコンポーネントのインスタンスを保持できる型アノテーションに利用できます。例えば以下の通りです:

class MyAwesomeComponent extends React.Component {
  render() {
    return <div>こんにちは</div>;
  }
}

const foo: React.ReactElement<MyAwesomeComponent> = <MyAwesomeComponent />; // Okay
const bar: React.ReactElement<MyAwesomeComponent> = <NotMyAwesomeComponent />; // Error!

もちろん、これを関数の引数や、コンポーネントのPropsの型として使用することもできます。

React JSXのヒント: propsを受け取り、JSXでレンダリングできるコンポーネントを受け入れる

型React.Component<Props>はReact.ComponentClass<P> | React.StatelessComponent<P>のように2つの種類のコンポーネントの型を統合しています。なので、Props型を受け取り、JSXを使ってレンダリングする_何か_を受け入れることができます。

const X: React.Component<Props> = foo; // どこかから渡されたコンポーネント

// XコンポーネントにPropsを渡して表示:
<X {...props}/>;

React JSXのヒント: ジェネリックコンポーネント

これは、期待どおりに動作します。以下に例を示します:

/** ジェネリックコンポーネント */
type SelectProps<T> = { items: T[] }
class Select<T> extends React.Component<SelectProps<T>, any> { }

/** 使い方 */
const Form = () => <Select<string> items={['a','b']} />;

ジェネリック関数

次のようなものがうまくいきます:

function foo<T>(x: T): T { return x; }

しかし、アロー関数のジェネリック関数を利用しようとすると、構文エラーになります。

const foo = <T>(x: T) => x; // ERROR : `T` タグが閉じられていません

回避策:ジェネリックのパラメータにextendsを使用すると、コンパイラがジェネリックであることを教えられます。extendsは、ジェネリックの型に制約を付けるためのキーワードです。{}をextendsする、ということは、オブジェクトであれば、何でも良い、ということです。なので、単に構文エラーを回避するために、このようにすることができます:

const foo = <T extends {}>(x: T) => x;

Reactのヒント: 厳密に型付けされたRef

基本的にRefの変数をユニオン型で定義することによって、nullで初期化できます。そして、それをコンポーネントのrefプロパティに渡したコールバック関数で初期化できます。

class Example extends React.Component {
  example() {
    // ... 何らかの処理
  }

  render() { return <div>Foo</div> }
}


class Use {
  exampleRef: Example | null = null; 

  render() {
    return <Example ref={exampleRef => this.exampleRef = exampleRef } />
  }
}

これは、DOM要素の参照を保持する変数についても同じです。

class FocusingInput extends React.Component<{ value: string, onChange: (value: string) => any }, {}>{
  input: HTMLInputElement | null = null;

  render() {
    return (
      <input
        ref={(input) => this.input = input}
        value={this.props.value}
        onChange={(e) => { this.props.onChange(e.target.value) } }
        />
      );
    }
    focus() {
      if (this.input != null) { this.input.focus() }
    }
}

型アサーション

デフォルトProps

  • デフォルト値のあるPropsを持ったステートフルなコンポーネント: Nullアサーション演算子?を使って、デフォルト値のあるPropsを定義できます。このPropsには、(外部からReactの仕組みによって)値が渡されます(これが最も理想的なものとは限りませんが、今思いつく限りでは、シンプルでミニマムなコードです)。

class Hello extends React.Component<{
  /**
   * @default 'TypeScript'
   */
  compiler?: string,
  framework: string
}> {
  static defaultProps = {
    compiler: 'TypeScript'
  }
  render() {
    const compiler = this.props.compiler!;
    return (
      <div>
        <div>{compiler}</div>
        <div>{this.props.framework}</div>
      </div>
    );
  }
}

ReactDOM.render(
  <Hello framework="React" />, // TypeScript React
  document.getElementById("root")
);
  • デフォルトPropsのあるFunctionコンポーネント :シンプルなJavaScriptの構文を活用して、TypeScriptの型システムとうまく組み合わせることをお勧めします。下記はその例です:

const Hello: React.FC<{
  /**
   * @default 'TypeScript'
   */
  compiler?: string,
  framework: string
}> = ({
  compiler = 'TypeScript', // デフォルト値のあるProps
  framework
}) => {
    return (
      <div>
        <div>{compiler}</div>
        <div>{framework}</div>
      </div>
    );
  };


ReactDOM.render(
  <Hello framework="React" />, // TypeScript React
  document.getElementById("root")
);

WebComponentの宣言

もしWebComponentを利用している場合、それはReactの型定義ファイル(@types/react)には定義されていません。しかし、アンビエント宣言(declare)を使って簡単に定義できます。例えば、my-awesome-sliderというWebComponentがあるとします。これは、MyAwesomeSliderPropsを受け取ります。この場合、以下のようになります:

declare global {
  namespace JSX {
    interface IntrinsicElements {
      'my-awesome-slider': MyAwesomeSliderProps;
    }

    interface MyAwesomeSliderProps extends React.Attributes {
      name: string;
    }
  }
}

のように、型アサーションにはas Foo構文を使います。

ブラウザ向けのクイックスタートで、すでにReactアプリケーションの開発のセットアップの仕方を説明しています
Create React App
Reactの公式Webサイト
既に説明した