React 19における ref as prop のTypeScript対応
React 19で導入された新しいref as prop機能により、forwardRefを使わずコンポーネントで直接refプロパティを受け取れるようになりました。しかし公式ドキュメントのTypeScript対応が不足しているため、適切な型付け方法に混乱が生じています。
問題の本質
- React 19で
refが通常のプロップスとして扱えるようになった - 公式サンプルがJavaScriptのみで型定義が不明
refプロパティにどんなTypeScript型を指定すべきか不透明- 既存の
React.RefObjectでは型エラーが発生するケース
✅ 推奨解決策: Ref<T> 型の使用
refプロパティには**React.Ref<T>型**を使用します。DOM要素またはコンポーネントインスタンスを適切に型付けできます。
import type { Ref } from 'react';
type Props = {
placeholder?: string;
ref?: Ref<HTMLInputElement>; // Ref型+オプショナル指定
};
function MyInput({ placeholder, ref }: Props) {
return <input placeholder={placeholder} ref={ref} />;
}function ParentComponent() {
const inputRef = useRef<HTMLInputElement>(null);
return (
<MyInput
ref={inputRef} // 正常に動作
placeholder="検索..."
/>
);
}必須ポイント
- 常にオプショナルとして定義
ref?: Ref<T>形式で宣言(必須ではないため) - 具体的な要素型を指定
HTMLInputElement、HTMLDivElementなど対象要素を厳密に - 汎用型で柔軟に対応
Ref<T>はRefObject<T> | ((instance: T) => void)を内包
🚫 RefObject<T>では不十分な理由
初期の回答で提案されたRefObjectでは関数型ref((ref) => {})を扱えず型エラーが発生します。
// 関数型refを受け付けないため実用性が低い
ref: React.RefObject<HTMLInputElement>;🔧 高度なケース: カスタム要素への対応
サードパーティライブラリなど、特殊なref処理が必要な場合の実装例:
import type { Ref } from 'react';
import type { LexicalEditor } from 'lexical';
type EditorProps = {
ref?: Ref<LexicalEditor>;
};
function RichTextEditor({ ref }: EditorProps) {
return (
<EditorRefPlugin
editorRef={(editorRef) => {
if (!ref) return;
// 関数型refとオブジェクト型refを両対応
typeof ref === 'function'
? ref(editorRef)
: (ref.current = editorRef);
}}
/>
);
}💡 代替アプローチ: ComponentPropsの活用
コンポーネントのprops全体を型継承する方法も有効です。ネイティブ要素の属性をそのまま利用できる利点があります。
import { ComponentProps } from 'react';
// input要素の全てのpropsを継承(ref含む)
function MyInput(props: ComponentProps<"input">) {
return <input {...props} />;
}
// 使用例
<MyInput ref={ref} placeholder="名前を入力" />;重要注意点
- Reactバージョン確認
React 19.0.0以上であることをpackage.jsonで確認 - 型定義の更新
@types/reactを最新版に更新 - 既存コンポーネント移行時
forwardRefとref as propの混在使用は非推奨 - テストの必須性
関数型ref・オブジェクト型refの両方で動作検証を実施
React 19のref as propは型安全性を保ちつつコンポーネント設計をシンプルにします。Ref<T>の適切な使用で、型エラーなしに新機能を活用可能です。