React Native と TypeScript 2026年版:型安全なアーキテクチャと面接対策
TypeScriptを活用した型安全なReact Nativeアプリを構築する方法を解説。Codegen、TurboModules、0.87で必須となったStrict TypeScript API、アーキテクチャパターン、型付きナビゲーション、ツールチェーン要件、面接質問を網羅する。

2026年半ばの時点で、React NativeにおけるTypeScriptの型安全性は大きく成熟している。バージョン0.87ではStrict TypeScript APIが必須のデフォルトとなり、大規模なツールチェーンの近代化が完了した。TypeScriptは、JavaScriptとネイティブコードをつなぐ単なるオプションのツールではなくなった。コンポーネントのpropsからTurboModuleのインターフェースに至るまで、アプリケーション全体の契約を駆動し、本番環境のクラッシュログではなくビルド時に不整合を検出する仕組みとなっている。
React Native 0.87(2026年8月)では、Strict TypeScript APIが必須のデフォルトとなった。また、Node.js 22.13以上、Kotlin 2.0以上、Android Gradle Plugin 9が最低要件として設定された。レガシーのディープインポートに対するオプトアウトは0.88までのみ利用可能である。
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:オプトインからデフォルトへ
Strict TypeScript APIはReact Native 0.80でオプトイン機能として導入された。0.87では、すべての新規プロジェクトで必須のデフォルトとなっている。型は手動でメンテナンスされるのではなく、React Nativeのソースコードから直接生成されるため、ドキュメント化されたAPIと実際の実装の間のズレが解消される。
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true
}
}この設定により、react-native/Libraries/Text/Textのようなサブパスからのインポートは型エラーとなる。すべてのインポートはルートのreact-nativeパッケージから行う必要がある。ライブラリや古いコードベースがディープインポートに依存している場合、0.88まで一時的なオプトアウトが利用可能である。
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
"customConditions": ["react-native", "react-native-legacy-deep-imports"]
}
}このオプトアウトは0.89で削除される。それまでに移行を完了する必要がある。
0.87のツールチェーン要件
React Native 0.87では、ビルドチェーン全体の最低バージョンが引き上げられた。
| コンポーネント | 最低要件 |
|---|---|
| Node.js | 22.13.0 |
| Kotlin | 2.0(バンドル版: 2.2.0) |
| Android Gradle Plugin | 9.x |
| Android compileSdk | 34(最小)、37(ターゲット) |
Androidでは、AGP 9に追加の設定が必要となる。
# android/gradle.properties
android.builtInKotlin=false
android.newDsl=falseこれらの要件は0.87以降を対象とするすべてのプロジェクトに適用される。New Architectureマイグレーションガイドでは、これらの変更の広範な背景が解説されている。
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とは何か、なぜ重要なのですか?
Strict TypeScript APIは、手書きの.d.tsファイルではなく、React Nativeのソースコードから直接型を生成する。0.87では必須のデフォルトとなった。インポートをルートのreact-nativeパッケージに制限し、ディープインポートを非推奨とする。これにより安定した公開APIサーフェスが定義され、利用者がstrict型のみを使用している限り、内部リファクタリングによって利用者のコードが破壊されることはない。customConditionsによる一時的なオプトアウトは0.88まで利用可能である。
ネストされたナビゲーター間で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 0.87で削除されたAPIは何ですか?
0.87ではInteractionManager(代わりにrequestIdleCallbackを使用)、NativeMethods / NativeMethodsMixin型(代わりにHostInstanceを使用)、いくつかのStatusBar propsが削除された。src/private/パスへのディープインポートは型エラーとなる。useTurboModulesフラグも削除された。TurboModulesは常に有効となっているためである。
React Nativeの面接質問の完全ガイドでは、アーキテクチャ、パフォーマンス、デバッグのトピックが網羅されている。
今すぐ練習を始めましょう!
面接シミュレーターと技術テストで知識をテストしましょう。
Sources
- React Native 0.87 Release Notes - Strict TypeScript APIのデフォルト化、ツールチェーン要件、API削除
- React Native TypeScript Documentation - 公式TypeScriptセットアップガイド
- React Navigation TypeScript Guide - 型付きナビゲーションパターン
- TanStack Query Documentation - 型推論を活用したデータフェッチ
React Native TypeScript 2026のポイント
- Strict TypeScript API(0.87で必須化)は安定した公開サーフェスにインポートを制限し、内部変更による破壊を防止する。レガシーのディープインポートに対するオプトアウトは0.88までのみ利用可能である
- Codegenは TypeScript仕様ファイルからネイティブインターフェースを生成し、JS-ネイティブ境界における型エラーをランタイムクラッシュからビルド時の失敗に移行させる
- 0.87のツールチェーン最低要件:Node.js 22.13以上、Kotlin 2.0以上、AGP 9、compileSdk 34以上
RootStackParamListとNativeStackScreenPropsを使った型付きナビゲーションパラメータにより、画面名の誤りやパラメータの欠落をアプリ実行前に検出できる- 判別共用体は画面状態を相互排他的な分岐としてモデル化し、不可能な状態を型レベルで表現不能にする
- 型付き仕様を持つTurboModulesは、旧来の
ReadableMap/NSDictionaryパースを置き換え、JavaScriptからC++、プラットフォームネイティブコードまで完全な型安全性を実現する - TanStack Queryを使ったジェネリックAPIフックは、エンドポイントからコンポーネントまで手動キャストなしで型推論を維持する
今すぐ練習を始めましょう!
面接シミュレーターと技術テストで知識をテストしましょう。
React Native のバグを見つけられますか
実際のコード、隠れたバグ、1日1回。アカウントなしで試せます。

執筆
Anthony Fillion-MailletSharpSkill 創業者
10 年以上フルスタック開発に携わっています。SharpSkill を運営し、ここで公開される内容に責任を負っています。
2026年8月25日 更新
タグ
共有
関連記事

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

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

Flutter vs React Native パフォーマンス比較 2026:ベンチマークと面接対策
Flutter 3.38とReact Native 0.82のパフォーマンスを徹底比較。Impellerエンジン、新アーキテクチャ、フレームレートベンチマーク、メモリ使用量、採用面接で頻出する質問を解説します。