React Native と TypeScript 2026年版:型安全なアーキテクチャと面接対策
2026年のReact NativeにおけるTypeScriptの型安全アーキテクチャを解説。Codegen、TurboModules、Strict TypeScript API、型付きナビゲーション、面接質問をコード例とともに紹介します。

2026年半ばの時点で、React NativeにおけるTypeScriptの型安全性は大きく成熟している。バージョン0.86ではReact 19.1、Strict TypeScript API、そしてCodegenを基盤とした完全なブリッジレスアーキテクチャが標準搭載されている。TypeScriptは、JavaScriptとネイティブコードをつなぐ単なるオプションのツールではなくなった。コンポーネントのpropsからTurboModuleのインターフェースに至るまで、アプリケーション全体の契約を駆動し、本番環境のクラッシュログではなくビルド時に不整合を検出する仕組みとなっている。
React Native 0.80でオプトイン方式のStrict TypeScript APIが導入され、0.82でレガシーブリッジが完全に廃止、0.85で最後のinteropレイヤーが削除された。2026年6月時点の0.86では、すべての新規プロジェクトがソースコードから直接生成されたTypeScript型を使用し、完全なブリッジレス構成で開始される。
TypeScriptがReact Nativeのデフォルトになった理由
バージョン0.76以降、npx react-native initコマンドで生成されるプロジェクトはすべてTypeScriptで構成されている。しかし、本質的な変化はネイティブ境界で起きた。Codegen導入以前、開発者はJavaScriptからObjective-CやKotlinへの境界を越える際に手動の型アサーションを記述していた。これは文字列ベースの暗黙的な契約であり、実行時に無言で破綻するものだった。
CodegenはTypeScriptの仕様ファイルを読み取り、C++、Objective-C++、Java/Kotlinのインターフェースを自動生成する。TypeScriptの仕様がnumberを返すメソッドを宣言すれば、生成されたネイティブインターフェースがその制約をコンパイル時に強制する。
React Nativeの公式ドキュメントでは基本的なセットアップが解説されているが、プロダクション環境で重要な型安全パターンはさらに先を行く。型付きナビゲーションスタック、ジェネリックAPIフック、状態マシン用のタグ付きユニオン、そしてCodegen駆動のTurboModule仕様がその中核を成す。
Strict TypeScript APIのセットアップ
React Native 0.80で導入されたStrict TypeScript APIは、ソースコードから直接生成された型のみに公開APIサーフェスを制限する。これにより、マイナーバージョン間で破壊される可能性のある内部モジュールへの偶発的な依存を防止できる。
{
"compilerOptions": {
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true,
"moduleResolution": "bundler",
"jsx": "react-jsx",
"types": ["react-native/types/strict"]
},
"extends": "@react-native/typescript-config/tsconfig.json"
}この設定により、react-native/Libraries/Text/Textのようなサブパスからのインポートは型エラーとなる。すべてのインポートはルートのreact-nativeパッケージから行う必要があり、0.80以降で強制されているディープインポートの非推奨化に準拠する形となる。
React Navigation 7による型安全なナビゲーション
React Navigation 7.xは、TypeScriptのファーストクラスサポートを提供している。基本パターンは、RootStackParamList型を定義して各画面名とそのパラメータをマッピングし、その型をナビゲーターと画面コンポーネントに伝播させるというものである。
export type RootStackParamList = {
Home: undefined;
Profile: { userId: string };
Settings: undefined;
ArticleDetail: { articleId: string; source: 'feed' | 'search' };
};
export type AppTabParamList = {
Dashboard: undefined;
Explore: { category?: string };
Notifications: undefined;
};画面コンポーネントは、手動キャストなしで型付きpropsを受け取る。
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
import type { RootStackParamList } from '../navigation/types';
type Props = NativeStackScreenProps<RootStackParamList, 'ArticleDetail'>;
export function ArticleDetailScreen({ route, navigation }: Props) {
// route.params.articleId は string — 型によって保証されている
// route.params.source は 'feed' | 'search' — ランタイムチェック不要
const { articleId, source } = route.params;
// navigation.navigate('Profile', { userId: '123' }) — 型チェック済み
// navigation.navigate('Profile', {}) — コンパイルエラー: userId が未指定
return (
<ArticleView id={articleId} referrer={source} />
);
}このパターンにより、ランタイムエラーの一分類が完全に排除される。誤ったパラメータや不足したパラメータで画面へ遷移しようとすると、アプリ実行前にビルド時に失敗する。
直接の画面子コンポーネントではないコンポーネントでは、useNavigation<NativeStackNavigationProp<RootStackParamList>>()を使用することで、propsの受け渡しなしに同等の型安全性を得られる。
Codegenによる型安全なTurboModuleの構築
TurboModulesは、旧来のNative Modulesシステムに取って代わるものである。TypeScriptの仕様ファイルが唯一の信頼できる情報源として機能し、Codegenがそこからネイティブインターフェースを生成する。仕様とネイティブ実装が乖離した場合、ビルドが失敗する。
import type { TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';
export interface Spec extends TurboModule {
getDeviceModel(): string;
getBatteryLevel(): Promise<number>;
getStorageInfo(): Promise<{
totalBytes: number;
freeBytes: number;
usedPercentage: number;
}>;
onBatteryChange(callback: (level: number) => void): void;
}
export default TurboModuleRegistry.getEnforcing<Spec>('DeviceInfo');npx react-native codegenを実行すると、対応するC++、Objective-C++、Javaインターフェースが生成される。ネイティブ実装はすべてのメソッドシグネチャと正確に一致する必要がある。例えば、getStorageInfoは3つの数値フィールドを持つオブジェクトを返す必要があり、異なる構造を返すとネイティブ側でコンパイルエラーが発生する。
class DeviceInfoModule(reactContext: ReactApplicationContext) :
NativeDeviceInfoSpec(reactContext) {
// 戻り値の型は生成されたNativeDeviceInfoSpecによって強制される
override fun getDeviceModel(): String {
return Build.MODEL
}
override fun getBatteryLevel(): Promise<Double> {
val bm = reactContext.getSystemService(Context.BATTERY_SERVICE)
as BatteryManager
val level = bm.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY
).toDouble()
return Promise.resolve(level)
}
}旧アーキテクチャで問題となっていたReadableMapやNSDictionaryのパース処理による暗黙の型変換バグが、このアプローチによって排除される。
React Nativeの面接対策はできていますか?
インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。
ジェネリック型を活用した型安全なAPIフック
再利用可能な型付きフックパターンにより、画面間でフェッチロジックを重複させることなく、完全な型推論を維持できる。
import { useQuery, UseQueryOptions } from '@tanstack/react-query';
interface ApiResponse<T> {
data: T;
meta: { page: number; totalPages: number };
}
export function useApiQuery<T>(
key: readonly string[],
endpoint: string,
options?: Omit<UseQueryOptions<ApiResponse<T>>, 'queryKey' | 'queryFn'>
) {
return useQuery<ApiResponse<T>>({
queryKey: key,
queryFn: async () => {
const response = await fetch(`${API_BASE}${endpoint}`);
if (!response.ok) throw new ApiError(response.status);
return response.json() as Promise<ApiResponse<T>>;
},
...options,
});
}
// 使用例 — T は Article[] として推論される
interface Article {
id: string;
title: string;
publishedAt: string;
}
const { data, isLoading } = useApiQuery<Article[]>(
['articles', 'latest'],
'/articles?sort=latest'
);
// data.data は Article[] — 完全に型付き
// data.meta.totalPages は numberジェネリックパラメータTは、フックの呼び出し元からクエリ関数、結果を利用するコンポーネントに至るまで、チェーン全体に伝播する。asによるキャストもany型も不要である。
判別共用体による状態マシンの設計
画面の複雑な状態(読み込み中、エラー、空、読み込み完了)は、オプショナルフィールドの集合ではなく、判別共用体としてモデル化するのが最適である。
type ScreenState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'error'; error: string; retryCount: number }
| { status: 'empty'; message: string }
| { status: 'loaded'; data: T; refreshedAt: Date };
// components/DataScreen.tsx
function renderContent<T>(state: ScreenState<T>, renderItem: (data: T) => ReactNode) {
switch (state.status) {
case 'idle':
return null;
case 'loading':
return <LoadingSpinner />;
case 'error':
// state.error はここでは string — TypeScriptが自動的に絞り込む
return <ErrorBanner message={state.error} retries={state.retryCount} />;
case 'empty':
return <EmptyState message={state.message} />;
case 'loaded':
// state.data は T — 完全に型付き
return renderItem(state.data);
}
}このパターンにより、不可能な状態を型レベルで表現不能にできる。loading状態が古いdataを誤って保持することはなく、error状態には常にデバッグのためのコンテキストが含まれる。
よくあるアンチパターン:{ isLoading: boolean; error?: string; data?: T }。この定義では{ isLoading: true, error: 'fail', data: [...] }のような状態が許容される — 3つの矛盾するシグナルが同時に存在する。判別共用体を使えば、このような状態を型レベルで防止できる。
React Native TypeScript 面接質問集
New ArchitectureとTypeScriptが標準となった2026年のシニアモバイルエンジニアリングチームの面接で実際に問われる質問を取り上げる。
CodegenはJavaScript-ネイティブ境界でどのように型安全性を実現していますか?
CodegenはTypeScript(またはFlow)の仕様ファイルを読み取り、C++、Objective-C++、Java/Kotlinのインターフェースコードを生成する。生成されたネイティブインターフェースは、仕様で定義されたメソッドシグネチャ、パラメータ型、戻り値型を正確に強制する。ネイティブ実装が乖離した場合 — 仕様がDoubleを宣言しているのにIntを返す、構造体からフィールドを省略するなど — ネイティブコンパイラがビルドを拒否する。これにより、型エラーがランタイムクラッシュからビルド時の失敗に移行する。
Strict TypeScript APIとは何か、なぜ重要なのですか?
React Native 0.80で導入されたStrict TypeScript APIは、手書きの.d.tsファイルではなく、React Nativeのソースコードから直接型を生成する。インポートをルートのreact-nativeパッケージに制限し、ディープインポートを非推奨とする。これにより安定した公開APIサーフェスが定義され、利用者がstrict型のみを使用している限り、内部リファクタリングによって利用者のコードが破壊されることはない。tsconfig.jsonで"types": ["react-native/types/strict"]を設定することで有効化できる。
ネストされたナビゲーター間でReact Navigationのパラメータをどのように型付けしますか?
ナビゲーターごとにParamList型を定義し、NavigatorScreenParamsを使用してそれらを合成する。スタック内にネストされたタブナビゲーターの場合、スタックのパラメータリストがタブのパラメータリストを参照する:type RootStack = { Main: NavigatorScreenParams<TabParamList>; Modal: { id: string } }。すべてのnavigate()呼び出しがネスト階層全体を通じて型チェックされ、画面名の誤りやパラメータの欠落がコンパイル時に検出される。
判別共用体はReact Nativeの状態管理でどのような問題を解決しますか?
判別共用体は、相互排他的な状態(loading、error、loaded)をユニオン型の別々の分岐として、statusフィールドをキーにしてモデル化する。TypeScriptはswitch文の各分岐で型を自動的に絞り込むため、state.dataへのアクセスはstate.status === 'loaded'の場合にのみ可能となる。これにより、読み込みインジケーターがエラーデータと同時に表示されるといったバグを防止できる。オプショナルフィールドやbooleanフラグでは、このクラスのバグを防ぐことはできない。
TurboModulesと旧来のNative Modulesシステムの違いを説明してください。
Native Modulesは非同期ブリッジを介して通信し、すべてのデータをJSONにシリアライズしていた。TurboModulesはJSI(JavaScript Interface)を使用して同期的かつ直接的なC++呼び出しを行い、シリアライズのオーバーヘッドがない。また、遅延読み込み(アプリ起動時ではなく初回使用時に読み込む)によりコールドスタート時間を削減し、Codegenを使用してTypeScript仕様から型安全なインターフェースを生成する。旧システムはReadableMap / NSDictionaryのパースによるランタイム型変換に依存していたが、TurboModulesはコンパイル時に型を強制する。
React Nativeの面接質問では、JSI、Fabric、ブリッジレスアーキテクチャについてさらに詳しく解説している。
今すぐ練習を始めましょう!
面接シミュレーターと技術テストで知識をテストしましょう。
まとめ
- Strict TypeScript API(0.80以降)は安定した公開サーフェスにインポートを制限し、内部変更による破壊を防止する — すべての新規プロジェクトで有効化すべきである
- Codegenは TypeScript仕様ファイルからネイティブインターフェースを生成し、JS-ネイティブ境界における型エラーをランタイムクラッシュからビルド時の失敗に移行させる
RootStackParamListとNativeStackScreenPropsを使った型付きナビゲーションパラメータにより、画面名の誤りやパラメータの欠落をアプリ実行前に検出できる- 判別共用体は画面状態を相互排他的な分岐としてモデル化し、不可能な状態を型レベルで表現不能にする
- 型付き仕様を持つTurboModulesは、旧来の
ReadableMap/NSDictionaryパースを置き換え、JavaScriptからC++、プラットフォームネイティブコードまで完全な型安全性を実現する - TanStack Queryを使ったジェネリックAPIフックは、エンドポイントからコンポーネントまで手動キャストなしで型推論を維持する
今すぐ練習を始めましょう!
面接シミュレーターと技術テストで知識をテストしましょう。
タグ
共有
関連記事

React Native 0.85(2026年):新アニメーションバックエンド、厳格なTypeScript APIと面接対策
React Native 0.85の共有アニメーションバックエンド、ポストブリッジアーキテクチャ、Metro TLSについて、コード例と面接質問を交えて徹底解説します。

2026年のReact Native新アーキテクチャ:Hermes V1、ブリッジレスモードとインタビュー質問
React Nativeの新アーキテクチャを徹底解説。Hermes V1エンジン、ブリッジレスモード、TurboModules、Fabricレンダラーの仕組み、パフォーマンスベンチマーク、移行ガイド、技術面接の質問と回答を網羅。

Expo RouterによるReact Nativeファイルベースナビゲーション完全ガイド
Expo Routerを使ったReact Nativeのファイルベースルーティングを徹底解説。レイアウト、ダイナミックルート、型安全なナビゲーション、タブ、モーダル、ミドルウェアまで、2026年最新のパターンを網羅します。