props の型を定義するとき、
- 組み込み要素の props を引き継ぐ
- 不適切な props 値を設定できないようにする
際に参考になりそうな事を記載します。
組み込み要素の props を自身のコンポーネントに加える
htmlの要素が持つ pops を自身が作成するコンポーネントでも使うとき、ひとつひとつ定義すると大変なことになりますよね。
そういうときは、JSX.IntrinsicElements が便利です。
例えば、自身が作成するコンポーネントで button を使っていて、button が持つ props を受け取れることを定義したいときは、
type MyButtonProps = JSX.IntrinsicElements['button'];
とすればOKです。自身のコンポーネント用に expanded: boolean という props があるなら、
type MyButtonProps = {
expanded: boolean;
} & JSX.IntrinsicElements['button'];
という形で定義できます。
props に設定が間違っている事が分かるようにする
props の定義で、組み合わせできない props の値が設定されても、エラーで気が付けるようにできます。
少し長いですが以下の様な形です。
import React from 'react';
type BaseProps = {
label: string;
}
type OrderedProps = {
listType: 'ordered';
listStyle: 'decimal' | 'cjk-decimal' | 'upper-roman';
} & BaseProps
& JSX.IntrinsicElements['ol'];
type UnorderedProps = {
listType: 'unordered';
listStyle: 'none' | 'disc' | 'circle' | 'square';
} & BaseProps
& JSX.IntrinsicElements['ul'];
type Props = OrderedProps | UnorderedProps;
export default function MyList(props: Props) {
const {
label,
listStyle,
children,
...otherProps
} = props;
let listEl = <></>;
if (props.listType === 'ordered') {
listEl = <ol
style={{ listStyleType: listStyle }}
{...(otherProps as JSX.IntrinsicElements['ol'])}
>{children}</ol>;
}
if (props.listType === 'unordered') {
listEl = <ul
style={{ listStyleType: listStyle }}
{...(otherProps as JSX.IntrinsicElements['ul'])}
>{children}</ul>;
}
return (
<div>
<div>{label}</div>
{listEl}
</div>
);
}
listType が
- ‘ordered’ なら、listStyle に使えるのは ‘decimal’, ‘cjk-decimal’, ‘upper-roman’
- ‘unordered’ なら、listStyle に使えるのは ‘none’, ‘disc’, ‘circle’, ‘square’
となるので、違っている場合は指摘されます。
Visual Studio Code 上なら、
listType が ‘ordered’ なら、
listStyle に ‘none’ は使えないので、
MyList に波線が付いて、間違っていることが分かります。
type として OrderedProps と UnorderedProps を定義して Props はそのどちらかとすることで、できない組み合わせを設定されたときでも間違いに気づけます。
type Props = OrderedProps | UnorderedProps;
VSCode で props のサジェストも追随してくれると更に楽なんですが、そこまで判断はされませんでした。
コメント