1.5.0-beta には入っていません (2015/07/21 追記: 1.5.3 にも入っていません。 1.6 で入る模様) が、 TypeScript の master ブランチでは、 JSX/React がサポートされています。
React/Flux の TodoMVC のサンプルコードを、これを使って TypeScript 化してみました。
コードはこちらから見られます。
こちらのサイトの説明を参考にさせていただきました。
ポイント
- JSX を書くときは拡張子を .tsx にする
- component は
React.Component<P, S>
を extends したクラスを作成する-
P
は props の型、S
は state の型 -
React.createClass
で作ると、クラス内でのthis
の参照がうまく解決できないので避けたほうがよいと思われる
-
-
getInitialState()
は、React.createClass
で作ったクラスでしか機能せず、上記の方法でクラスを作った場合は使えない- メソッドを定義するとコンソールに warning が出力され、実際 state が undefined になってしまう
- constructor で初期化すれば OK (constructor の引数が props なので、 state の初期値が props に依存する場合でも対応可)
- tsc のオプションの
--jsx
-
preserve
: jsx の記法のまま (<div/>
-><div/>
) -
react
: react のメソッドを使った記法に変換される (<div/>
->React.createElement("div")
) - サンプルコードでは、 JS 変換後に reactify とかするのが面倒だったので、
--jsx react
しました
-
サンプル
一例として、 TodoTextInput.tsx のコードを貼っておきます。
/// <reference path="../../typings/tsd.d.ts" />
import * as React from 'react';
let ENTER_KEY_CODE = 13;
export interface Props {
className?: string;
id?: string;
placeholder?: string;
onSave: (value: string) => void;
value?: string;
}
export default class TodoTextInput extends React.Component<Props, {value: string;}> {
constructor(props: Props) {
super(props);
this.state = { 'value': props.value ? props.value : '' };
}
render(): JSX.Element {
return (
<input
className={this.props.className}
id={this.props.id}
placeholder={this.props.placeholder}
onBlur={() => {
this.save();
}}
onChange={(event: React.FormEvent) => {
this.onChange(event);
}}
onKeyDown={(event: React.KeyboardEvent) => {
this.onKeyDown(event);
}}
value={this.state.value}
autoFocus={true}
/>
);
}
private save(): void {
this.props.onSave(this.state.value);
this.setState({ 'value': '' });
}
private onChange(event: React.FormEvent): void {
this.setState({ 'value': event.target['value'] });
}
private onKeyDown(event: React.KeyboardEvent): void {
if (event.keyCode === ENTER_KEY_CODE) {
this.save();
}
}
}
ちなみに
単に TypeScript の JSX/React サポートを試すだけなら、 component だけ書いておけばよかったわけですが、なぜ Flux 一式書いてみたかというと、 ts-eventemitter という自作ライブラリを試してみたかったからです。
それについては別途記事を書く予定です。 -> 書きました TypeScript の機能で EventEmitter のイベントの payload を型安全に扱う