※このブログではサーバー運用、技術の検証等の費用のため広告をいれています。
記事が見づらいなどの問題がありましたらContactからお知らせください。


【TypeScript】Reactの関数型コンポーネントの引数の型指定について

react web開発 フロント開発 React.FC TypeScript 型付き言語

投稿日:2021年2月6日

このエントリーをはてなブックマークに追加
TypeScriptでReactアプリケーションを作成した場合、関数型コンポーネントの引数の型指定に少し注意が必要です。

関数型Component

TypeScriptは型付き言語であるため関数の引数の型は常に意識する必要があります。

Reactのコンポーネントを記述するときも同様です。

propsを受け取らないとき

propsを受け取らない場合はjavascriptで記述する場合と変わりません。

import React from "react";

const SampleComponent = () => {
    return (<div>Hello World!!</div>)
}

export default SampleComponent;

このとき引数の型は指定していませんが実際には暗黙的な型推論が行われ、
この関数はReact.FC<{}>という型エイリアスとして認識されています。

つまり型指定して書くと以下のように書くことができます。

import React from "react";


const SampleComponent: React.FC<{}> = () => {
    return (<div>Hello World</div>)
}

ジェネリック型エイリアスのReact.FC<P>Pはpropsの型です。

しかし、はじめの例ではPを指定しませんでした。

なぜでしょうか?

ここでReact.FC<P>の定義を見ると、以下のようになっています。

/node_modules/@types/react/index.d.ts
type FC<P = {}> = FunctionComponent<P>;

なるほど、Generic型エイリアスのPにはデフォルトの型として空の型{}が指定してあったんですね。

propsとして値を受け取る場合

propsとして記述する場合には以下のように書きます。

import React from "react";

interface Props {
    name: string;
    age: number;
    children?: React.ReactNode;
}


const SampleComponent = (props: Props) => {
    return (<div>
        <div>{props.name}</div>
        <div>{props.age}</div>
        {props.children && <div>{props.children}</div>}
    </div>)
}

export default SampleComponent;

Propsという型エイリアスではchildrenをオプション引数として受け取っています。

childrenにはタグの中の子要素が自動的に渡されます。

タグの中に入る子要素はJSXで記述された要素JSXで記述された複数の要素文字列複数の文字列と4つのパターンが考えられます。

Reactは子要素として考えられる上記すべての要素をカバーしたReact.ReactNodeという型を提供しています。

propsの型指定はReact.FC<P>をつかって以下のように書くこともできます。

import React from "react";

interface Props {
    name: string;
    age: number;
}


const SampleComponent: React.FC<Props> = (props) => {
    return (<div>
        <div>{props.name}</div>
        <div>{props.age}</div>
        {props.children && <div>{props.children}</div>}
    </div>)
}

export default SampleComponent;

ここでインターフェイスPropsのオプション引数であるchildrenが削除されたことに注意してください。

実はReact.FC<P>Pという型は内部でchildrenという値をオプションで受け取れるように拡張されているのです。

前の例のようにpropsに型を指定した際には最終的な型がPropsになるのですが、React.FC<P>で指定した場合はchildrenが拡張された型が最終的なpropsの型になるのです。

React.FC<P>とpropsの型指定どっちを使うべき?

propsの型の指定とReact.FC<P>の型エイリアスを使った型指定、どちらでも良さそうですが、どちらを使うべきなのでしょうか?

結論からいうと、僕は必ずpropsの型指定にすべきだと考えています。

僕はTypeScriptで書く際には受け取れる値についてはすべて明確にしておくべきだと考えています。

React.FC<P>で書いた場合、childrenをレンダリングする機能がコンポーネントに備わっていなくてもchildrenが受け取れてしまいます。

そのため複数人のプロジェクトの場合、

「あの人が作ったこのコンポーネント、子要素がレンダリングされないぞ?バグかな〜…」

といった事態になりかねません。

せっかくTypeScriptを使ったのだからより安全に書きたいですね〜。

このエントリーをはてなブックマークに追加


関連記事

記事へのコメント