React

Type ScriptとReactのPRO Eggheadコース

セットアップ

私たちのブラウザ向けのクイックスタートに、すでにReactアプリケーションの開発のセットアップの仕方を説明しています。主なハイライトは次の通りです。

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

  • あなたのtsconfig.jsoncompilerOptionsで `"jsx" : "react"を使ってください。

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

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

HTMLタグとComponentの違い

Reactは、HTMLタグ(文字列)またはReact Component(クラス)をレンダリングします。これらに対するJavaScriptの出力は異なります(React.createElement( 'div')React.createElement(MyComponent))。これが決まる方法は最初の文字のケース(大文字小文字)です。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;
/// so on ...
}
}

ステートレスな関数コンポーネント(Stateless Functional Components)

あなたは単にReact.SFCインターフェースを使ってステートレスなコンポーネントを定義することができます。

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

ステートフルなコンポーネント(Stateful Components)

コンポーネントは、コンポーネントのpropsプロパティに基づいて型チェックされます。これは、JSXがどのように変換されるかによってモデル化されています。例えば属性がコンポーネントのpropsになるようにモデル化されています。

ReactのStatefulコンポーネントを作成するには、ES6クラスを使用します。react.d.tsファイルはあなた自身のPropsStateインターフェースを提供する、あなたのクラスで継承するべきReact.Component<Props,State>クラスを定義しています。これは以下のとおりです:

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

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

ReactはJSXstringのようなものをレンダリングすることができます。これらはすべて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="This is header." body="This is body." />

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

React型の定義は、React.ReactElement<T>を提供しており、<T/>クラスコンポーネントのインスタンスにアノテーションを付けることができます。例えば

class MyAwesomeComponent extends React.Component {
render() {
return <div>Hello</div>;
}
}
const foo: React.ReactElement<MyAwesomeComponent> = <MyAwesomeComponent />; // Okay
const bar: React.ReactElement<MyAwesomeComponent> = <NotMyAwesomeComponent />; // Error!

もちろん、これを関数の引数のアノテーションやReact componentのprop memberとして使用することもできます。

React JSXヒント: propに作用し、JSXを使用してレンダリングできるComponentを受け入れる

React.Component<Props>React.ComponentClass<P> | React.StatelessComponent<P>を統合しています。なので、Props型を受け取り、JSXを使ってレンダリングする何かを受け入れることができます。

const X: React.Component<Props> = foo; // from somewhere
// Render X with some props:
<X {...props}/>;

React JSXヒント:ジェネリックコンポーネント(Generic Components)

期待どおりに動作します。次に例を示します。

/** A generic component */
type SelectProps<T> = { items: T[] }
class Select<T> extends React.Component<SelectProps<T>, any> { }
/** Usage */
const Form = () => <Select<string> items={['a','b']} />;

ジェネリック関数(Generic Functions)

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

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

しかし、アローのジェネリック関数を使用しても、うまくいきません:

const foo = <T>(x: T) => x; // ERROR : unclosed `T` tag

回避策:ジェネリックパラメータにextendsを使用すると、コンパイラがジェネリックであることを教えられます。

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

Reactのヒント: React Tip: 厳密に型付けされた参照(Strongly Typed Refs)

あなたは基本的に参照のユニオンとして変数をnullで初期化できます。そしてそれをコールバックとして初期化できます。

class Example extends React.Component {
example() {
// ... something
}
render() { return <div>Foo</div> }
}
class Use {
exampleRef: Example | null = null;
render() {
return <Example ref={exampleRef => this.exampleRef = exampleRef } />
}
}

そしてネイティブ要素の参照に対しても同じです。

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(this.ctrls.input.value) } }
/>
);
}
focus() {
if (this.input != null) { this.input.focus() }
}
}

型アサーション(Type Assertions)

我々が 前に述べた のように、型アサーションにはas Foo構文を使います。

デフォルトProps(Default Props)

  • デフォルトPropsを持ったステートフルなコンポーネント:あなたはNullアサーション演算子を使って、プロパティが外部から(Reactによって)提供されることをTypeScriptに伝えることができます(これは理想的ではありませんが、しかし私が思いつく中では、最もシンプルでミニマムなコードです)。

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を備えたSFC :シンプルなJavaScriptパターンを活用してTypeScriptの型システムとうまく動作するようにすることをお勧めします。

const Hello: React.SFC<{
/**
* @default 'TypeScript'
*/
compiler?: string,
framework: string
}> = ({
compiler = 'TypeScript', // Default prop
framework
}) => {
return (
<div>
<div>{compiler}</div>
<div>{framework}</div>
</div>
);
};
ReactDOM.render(
<Hello framework="React" />, // TypeScript React
document.getElementById("root")
);