Skip to content

useRefとTypeScript - LegacyRef<HTMLDivElement>への型エラー解決

ReactのuseRefフックをTypeScriptで使用する際、LegacyRef<HTMLDivElement>への割り当てができないというエラーに遭遇することがあります。この問題は、適切な型指定とReactのrefシステムの理解が不足している場合に発生します。

問題の特定

エラーメッセージ「not assignable to type 'LegacyRef<HTMLDivElement> | undefined'」は、主に以下の原因で発生します:

  • 間違ったHTML要素型の指定
  • null初期化の欠落
  • ジェネリック型とコンポーネント期待型の不一致

解決策

1. 正しいHTML要素型の使用

HTMLElementではなく、より具体的な要素型を使用する必要があります。

typescript
// ❌ 間違った例
const ref = useRef<HTMLElement>(null);

// ✅ 正しい例
const divRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const svgRef = useRef<SVGSVGElement>(null);
const iframeRef = useRef<HTMLIFrameElement>(null);

2. nullでの初期化

useRefは必ずnullで初期化する必要があります。

typescript
// ❌ 間違った例
const ref = useRef<HTMLDivElement>();

// ✅ 正しい例
const ref = useRef<HTMLDivElement>(null);

3. 完全なコード例

typescript
import React, { useRef } from 'react';

function Test() {
    const node = useRef<HTMLDivElement>(null);

    if (node.current) {
        // 安全にプロパティにアクセス
        console.log(node.current.clientWidth);
    }

    return <div ref={node}>コンテンツ</div>;
}

カスタムフックでの汎用的な使用

複数の要素タイプで再利用可能なカスタムフックを作成する場合は、ジェネリック型を使用します。

typescript
const useCustomHook = <T extends HTMLElement = HTMLDivElement>() => {
    const elementRef = useRef<T>(null);
    
    // カスタムロジック
    React.useEffect(() => {
        if (elementRef.current) {
            // 要素に対する操作
        }
    }, []);
    
    return elementRef;
};

// 使用例
function MyComponent() {
    const buttonRef = useCustomHook<HTMLButtonElement>();
    const divRef = useCustomHook<HTMLDivElement>();
    
    return (
        <>
            <button ref={buttonRef}>ボタン</button>
            <div ref={divRef}>コンテンツ</div>
        </>
    );
}

注意

as unknown as ...のような型アサーションは、型システムを迂回するため避けるべきです。代わりに適切な型指定を行いましょう。

型システムの理解

Reactのrefシステムは以下の型定義を持っています:

typescript
interface RefObject<T> {
    readonly current: T | null;
}

type LegacyRef<T> = RefObject<T> | ((instance: T | null) => void) | null;

useRefは渡される初期値によって異なる型を返します:

  • useRef<T>(initialValue: T): MutableRefObject<T>
  • useRef<T>(initialValue: T | null): RefObject<T>
  • useRef<T = undefined>(): MutableRefObject<T | undefined>

まとめ

useRefのTypeScriptエラーを解決するには:

  1. 具体的なHTML要素型(HTMLDivElementなど)を使用する
  2. 必ずnullで初期化する
  3. ジェネリック型を使用して再利用可能なコンポーネントを作成する
  4. 型アサーションではなく適切な型指定を行う

これらの原則に従うことで、型安全でメンテナンスしやすいReactコンポーネントを作成できます。