Help us understand the problem. What is going on with this article?

TypeScript の JSX/React サポートを試す

More than 3 years have passed since last update.

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 を型安全に扱う

kimamula
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした