React 18 TypeScript で children プロパティがエラーになる問題
更新情報
この記事は React 18 と TypeScript の組み合わせにおける children
プロパティの型エラー問題について解説しています(2024年3月時点)。
問題点
React 18 にアップグレード後、children
プロパティを使用するすべてのコンポーネントで次のような TypeScript エラーが発生します:
Property 'children' does not exist on type 'IPageProps'
これは React 18 で React.FC
(FunctionComponent)の型定義から children
プロパティが削除されたためです。以前は自動的に含まれていたため、明示的に定義する必要はありませんでした。
原因
React 18 では、React.FC
インターフェースから children
プロパティが削除されました。これにより、以下のような問題を防ぐことができます:
const ComponentWithNoChildren: React.FC = () => <>Hello</>;
// このコンポーネントは children を受け付けないため、
// 以下の使用法は誤りですが、以前の型定義では検出できませんでした
<ComponentWithNoChildren>
<UnusedChildrenSinceComponentHasNoChildren />
</ComponentWithNoChildren>
解決策
方法1: PropsWithChildren を使用する
React.PropsWithChildren
ヘルパータイプを使用して、children を明示的に含めます。
import React from 'react';
const Component: React.FC<React.PropsWithChildren> = ({children}) => {
// コンポーネントの実装
}
import React from 'react';
interface Props {
title: string;
}
const Component: React.FC<React.PropsWithChildren<Props>> = ({title, children}) => {
return (
<div>
<h1>{title}</h1>
{children}
</div>
);
}
方法2: インターフェースで children を明示的に定義する
interface Props {
children: React.ReactNode;
// 他のプロパティ...
}
const Component: React.FC<Props> = ({children}) => {
// コンポーネントの実装
}
interface Props {
children?: React.ReactNode;
// 他のプロパティ...
}
const Component: React.FC<Props> = ({children}) => {
// コンポーネントの実装
}
方法3: カスタム型を定義する
よく使用する場合は、独自の型エイリアスを作成すると便利です。
// types/react.d.ts などに定義
import { FC, PropsWithChildren } from 'react';
export type FCC<P = {}> = FC<PropsWithChildren<P>>;
使用例:
import { FCC } from '../types/react';
interface MyProps {
title: string;
}
const MyComponent: FCC<MyProps> = ({title, children}) => {
return (
<div>
<h1>{title}</h1>
{children}
</div>
);
}
方法4: React.FC の使用をやめる
React.FC
を使用せず、通常の関数としてコンポーネントを定義する方法もあります。
type Props = {
title: string;
};
export function Component({title}: Props) {
return <h1>{title}</h1>;
}
type Props = {
children: React.ReactNode;
title: string;
};
export function Component({title, children}: Props) {
return (
<div>
<h1>{title}</h1>
{children}
</div>
);
}
推奨アプローチ
ベストプラクティス
- 新しいプロジェクト: 方法4(
React.FC
を使用しない)を推奨 - 既存プロジェクト: 方法3(カスタム型
FCC
)で段階的に移行 - 小規模修正: 方法1や方法2で個別に対応
互換性のための回避策(非推奨)
以下の方法は型定義を React 17 以前の状態に戻しますが、将来的な互換性の問題が発生する可能性があるため非推奨です。
// react.d.ts
import * as React from '@types/react';
declare module 'react' {
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
}
}
まとめ
React 18 での children
プロパティの型エラーは、意図的な変更によるものです。この変更により、コンポーネントが実際に children を受け入れるかどうかを明示的にする必要が生じ、より安全なコードを書くことができます。
適切な解決策を選択し、プロジェクトのニーズに合わせて対応してください。
注意
TypeScript と React の型定義は頻繁に更新されるため、定期的に最新のベストプラクティスを確認することをお勧めします。