実務でのTypeScript、型ってどこまでやる?

アイキャッチ画像

TypeScriptを使った開発が当たり前になりつつある今、「どこまで型をきっちり書くべき?」と悩む場面は少なくありません。型安全を意識するあまりに冗長なコードになることもあれば、逆に any で逃げすぎて型の恩恵を受けられないこともあります。

この記事では、実際の開発経験を踏まえつつ「これくらいやっておけば安心」という現場でのバランス感覚を紹介します。

型注釈は「必要なときだけ」でOK

const foo = “hello” as string;

このように明らかなリテラルに対して as string をつけるのは基本的に不要です。「推論で足りるところは任せてしまう」というスタンスで問題ないように感じます。

ただし、関数の戻り値・props・外部APIとのインターフェースなど、境界となる部分には明示的な型定義が必要です。

type と interface、どっちを使う?

結論としては、どちらでもよいです。ただし、プロジェクト内で統一することが重要です。

・type:ユニオン型やマップ型など応用が利きやすい

・interface:拡張性(extends)に強い

ReactのProps定義など、どちらでも書ける場面は多いですが、チーム内で「このプロジェクトでは type を使う」などルールを決めておくと混乱を防げます。

イベントハンドラなどの型は手を抜かない

例えば、Reactでボタンのクリックイベントを扱う場合、よくあるのが以下のような書き方。

type Props = {

  onClick: () => void;

}

一見問題なさそうですが、以下のように書いたほうが保守性が高くなります。

type Props = React.ButtonHTMLAttributes<HTMLButtonElement>;

こうしておけば、disabled や type などの属性も型で補完され、将来的な変更にも強くなります。

JSXでは <string> より as string を使う

const name = “Name” as string;

const name2 = <string>”Name”; // 非推奨

どちらも意味は同じですが、JSXでは <string> を使うとタグと解釈されてしまう可能性があります。そのため、実務では as string を使うのが基本です。

any を使ってもいいけど「逃げ道」にしない

開発初期や検証段階では any を使って「まず動かす」のは悪いことではありません。ただし、最終的には具体的な型に書き換える意識が必要です。

const data: unknown = getData();

if (typeof data === “string”) {

  // 型チェックで扱えるようになる

}

unknown などを使って、段階的に型を絞っていくのも選択肢の一つです。

「この型、いる?いらない?」の見極めポイント

実際の開発現場では、次のような問題に遭遇することがあります。

・型が細かすぎて修正が大変

・型が曖昧すぎてバグにつながった

・type と interface が混在していて統一感がない

これらを避けるには、「推論に任せられる部分は任せて、外部との境界はきちんと守る」というスタンスが現実的です。

まとめ:「型」はツール。全部を制覇しなくても大丈夫

TypeScriptの型システムは非常に奥が深く、Mapped型やConditional型、Utility Typesなど覚えることは無数にあります。

でも、実務では以下のポイントさえ押さえておけば安心です。

・基本は型推論に任せる

・外部からアクセスされる部分(Props、APIレスポンス、戻り値など)には明示的な型を書く

・チーム内で type または interface を統一する

・JSX内では <string> より as string を使う

・any は一時的な避難所。最終的には具体的な型にする

TypeScriptは「完璧にするため」ではなく、「チーム全体が安心して書けるコード」のためのツール。だからこそ、適度な型定義とルールが大切だと感じました。