TypeScriptによるStateless Functional Componentの定義
環境構築は create-react-app
とMicrosoft/TypeScript-React-Starterでサクッと行う
$ npx create-react-app my-app --scripts-version=react-scripts-ts $ cd my-app $ npm run start
以前、TypeScriptでReact app作ろうとしてセットアップに手間取ったときとは隔世の感がある。
type React.SFCを使う
@types/react
に React.SFC
という型が用意されているので、これを使う
DefinitelyTyped/index.d.ts at master · DefinitelyTyped/DefinitelyTyped
type SFC<P = {}> = StatelessComponent<P>; interface StatelessComponent<P = {}> { (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | null; propTypes?: ValidationMap<P>; contextTypes?: ValidationMap<any>; defaultProps?: Partial<P>; displayName?: string; }
type SFC<P = {}>
とあるので、全てのpropsはoptionalにする必要がある。
そのため、requiredで定義すると以下のコンパイルエラーが発生する。
error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & AppProps & { children?: ReactNode; }'. Type '{}' is not assignable to type 'AppProps'. Property 'name' is missing in type '{}'.
コンポーネントの書き換え
App.tsxをStateless Functional Componentに書き換えるとこのようになる
import * as React from 'react'; import './App.css'; const logo = require('./logo.svg'); interface AppProps { name?: string; } const App: React.SFC<AppProps> = ({ name }) => { return ( <div className="App"> <div className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h2>Welcome to {name}</h2> </div> <p className="App-intro"> To get started, edit <code>src/App.tsx</code> and save to reload. </p> </div> ); }; App.defaultProps = { name: 'React.SFC', }; export default App;
defaultPropsの定義をコンポーネント定義と分けたくない場合は、
const App: React.SFC<AppProps> = ({ name = 'React.SFC' }) => { return ( <div className="App"> ...
とも書ける