TypeScriptは素晴らしいです。 Reactもそうです。 両方一緒に使いましょう! TypeScriptを使用すると、IntelliSenseのメリットを享受できるだけでなく、コードについてさらに推論することができます。 これに加えて、TypeScriptの採用は低摩擦です。これは、プロジェクトの残りの部分で問題を引き起こすことなく、ファイルを段階的にアップグレードできるためです。

新しいReactプロジェクトを作成し、TypeScriptを統合することから始めましょう。 次のコマンドを実行して、プロジェクトを開始します。

# Make a new directory
$ mkdir react-typescript

# Change to this directory within the terminal
$ cd react-typescript

# Initialise a new npm project with defaults
$ npm init -y

# Install React dependencies
$ npm install react react-dom

# Make index.html and App.tsx in src folder
$ mkdir src
$ cd src
$ touch index.html
$ touch App.tsx

# Open the directory in your favorite editor
$ code .

次に、次のようにindex.htmlファイルを作成できます。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>React + TypeScript</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <div id="main"></div>
  <script src="./App.tsx"></script>
</body>
</html>

バンドラーとしてParcelを使用しますが、必要に応じてwebpackまたは別のバンドラーを使用することもできます。 または、Create React Appを使用する場合は、このセクションを確認してください。 プロジェクトにParcelを追加しましょう。

# Install Parcel to our DevDependencies
$ npm i parcel-bundler -D

# Install TypeScript
$ npm i typescript -D

# Install types for React and ReactDOM
$ npm i -D @types/react @types/react-dom

package.jsonを、開発サーバーを起動する新しいタスクで更新できます。

{
  "name": "react-typescript",
  "version": "1.0.0",
  "description": "An example of how to use React and TypeScript with Parcel",
  "scripts": {
    "dev": "parcel src/index.html"
  },
  "keywords": [],
  "author": "Paul Halliday",
  "license": "MIT"
}

これで、Counter.tsxファイルに単純なカウンターを設定できます。

import * as React from 'react';

export default class Counter extends React.Component {
  state = {
    count: 0
  };

  increment = () => {
    this.setState({
      count: (this.state.count + 1)
    });
  };

  decrement = () => {
    this.setState({
      count: (this.state.count - 1)
    });
  };

  render () {
    return (
      <div>
        <h1>{this.state.count}</h1>
        <button onClick={this.increment}>Increment</button>
        <button onClick={this.decrement}>Decrement</button>
      </div>
    );
  }
}

次に、App.tsxの内部で、カウンターをロードできます。

import * as React from 'react';
import { render } from 'react-dom';

import Counter from './Counter';

render(<Counter />, document.getElementById('main'));

私たちのプロジェクトは$ npm run devで実行でき、http://localhost:1234でアクセスできます。

ReactアプリとTypeScriptを作成する

Create React App を使用してプロジェクトを開始したい場合は、CRAがTypeScriptをすぐにサポートすることを知っていただければ幸いです。

create-react-appコマンドを呼び出すときは、--typescriptフラグを使用するだけです。

$ create-react-app my-new-app --typescript

機能コンポーネント

ステートレスまたは機能コンポーネントは、次のようにTypeScriptで定義できます。

import * as React from 'react';

const Count: React.FunctionComponent<{
  count: number;
}> = (props) => {
  return <h1>{props.count}</h1>;
};

export default Count;

React.FunctionComponentを使用して、予想される小道具のオブジェクト構造を定義しています。 このシナリオでは、countという名前の単一の小道具で渡されることを期待しており、インラインで定義しています。 Propsなどのインターフェイスを作成することで、これを他の方法で定義することもできます。

interface Props {
  count: number;
}

const Count: React.FunctionComponent<Props> = (props) => {
  return <h1>{props.count}</h1>;
};

クラスコンポーネント

クラスコンポーネントも同様にTypeScriptで次のように定義できます。

import * as React from 'react';

import Count from './Count';

interface Props {}

interface State {
  count: number;
};

export default class Counter extends React.Component<Props, State> {
  state: State = {
    count: 0
  };

  increment = () => {
    this.setState({
      count: (this.state.count + 1)
    });
  };

  decrement = () => {
    this.setState({
      count: (this.state.count - 1)
    });
  };

  render () {
    return (
      <div>
        <Count count={this.state.count} />
        <button onClick={this.increment}>Increment</button>
        <button onClick={this.decrement}>Decrement</button>
      </div>
    );
  }
}

デフォルトの小道具

デフォルトの小道具を設定したいシナリオでdefaultPropsを定義することもできます。 これを示すために、カウントの例を更新できます。

import * as React from 'react';

interface Props {
  count?: number;
}

export default class Count extends React.Component<Props> {
  static defaultProps: Props = {
    count: 10
  };

  render () {
    return <h1>{this.props.count}</h1>;
  }
}

this.state.countCounterコンポーネントに渡すのも停止する必要があります。これにより、デフォルトのプロップが上書きされます。

render () {
  return (
    <div>
      <Count />
      <button onClick={this.increment}>Increment</button>
      <button onClick={this.decrement}>Decrement</button>
    </div>
  )
}

これで、TypeScriptとReactを使用するように設定されたプロジェクトと、独自の関数型およびクラスベースのコンポーネントを作成するためのツールができました。