概要
React Native 0.80 では、JavaScript API に対して 2 つの重要な変更を導入します — react-native パッケージの deep imports の非推奨化と、新しい Strict TypeScript API(オプトイン)。これらは API を正確に定義し、利用者やフレームワークに対して信頼できる型安全性を提供する継続的な取り組みの一部です。
クイック要点
- Deep imports の非推奨化:0.80 から react-native パッケージの深いサブパス import に対して非推奨警告を導入します。
- Strict TypeScript API(オプトイン):ソースから生成された TypeScript 型と TypeScript 上の新しい公開 API ベースラインを導入します。より強力で将来性のある型の正確性を提供し、これは一度だけの破壊的変更になります。プロジェクトの tsconfig.json の compilerOptions でオプトインします。コミュニティと協力して十分にテストしたうえで、将来のリリースでデフォルト有効にする予定です。
何が変わるか、なぜか
我々は React Native の公開 JavaScript API(つまり import 'react-native' で得られるもの)を改善・安定化しようとしています。これまでは近似的に提供してきました。React Native 自体は Flow で作られていますが、コミュニティはオープンソースで TypeScript を主に使用しており、公開 API の消費と互換性検証は TypeScript 側で行われています。
従来の型定義はコミュニティが寄せてくれたもので(愛を込めて)、コードベースに統合・整列してきましたが、手動でのメンテナンスと自動化ツールの不在により正確性にギャップが生じていました。また、公開 JS API はモジュール境界が不明瞭で、内部の react-native/Libraries/ の deep imports がアプリコードから参照できる一方で、内部変更により頻繁に変更されていました。
0.80 では、deep imports の非推奨化と TypeScript での新しい生成ベースの API(Strict TypeScript API)へのオプトインを導入してこれらの問題に対処します。最終的にこれは将来の安定した React Native API を提供するための基盤作りです。
react-native からの deep imports の非推奨
現在行っている主な変更は、deep imports の使用を非推奨化することです(RFC)。ESLint と JS コンソールに警告を出します。値や型の deep imports は react-native のルート import に更新する必要があります。
// Before - import from subpath
import { Alert } from 'react-native/Libraries/Alert/Alert';
// After - import from `react-native`
import { Alert } from 'react-native';
この変更により、JavaScript API の公開表面積を固定されたエクスポートの集合に減らし、将来のリリースで安定化できるようにします。これらの import パスは 0.82 で削除することを目標にしています。
API フィードバック
ルートでエクスポートされていない API は deep imports を使わないと利用できなくなります。公開 API に含めるエクスポート内容についてはオープンなフィードバックスレッドを用意しており、コミュニティと協力して最終化していきます。ぜひフィードバックをお寄せください。
オプトアウト(警告を無効化)
将来的に deep imports を React Native の API から削除する予定であることに留意してください。可能な限りルート import に更新してください。
ESLint の警告を無効にする(一般)
.eslintrc.js の overrides を使って no-deep-imports ルールを無効化できます。
overrides: [
{
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
rules: {
'@react-native/no-deep-imports': 0,
},
},
]
コンソール警告の無効化(一般)
@react-native/babel-preset に disableDeepImportWarnings オプションを渡します。
module.exports = {
presets: [
[
'module:@react-native/babel-preset',
{ disableDeepImportWarnings: true },
],
],
};
Metro のキャッシュをクリアするためにアプリを再起動してください。
npx @react-native-community/cli start
オプトアウト(Expo)
ESLint の設定は上記と同様に overrides を使って無効化できます。
コンソール警告は babel-preset-expo に同様のオプションを渡します。
module.exports = function (api) {
api.cache(true);
return {
presets: [
['babel-preset-expo', { disableDeepImportWarnings: true }],
],
};
};
Metro のキャッシュをクリアするためにアプリを再起動してください。
npx expo start
Strict TypeScript API(オプトイン)
Strict TypeScript API は react-native パッケージ内に追加される新しい TypeScript 型群で、tsconfig.json でオプトインできます。既存の TS 型と並行して配布するため、準備ができたときに移行できます。
新しい型の特徴:
- ソースから直接生成される — カバレッジと正確性が向上し、より強い互換性保証が期待できます。
- react-native の index ファイルに限定される — 公開 API を厳密に定義することで、内部ファイルの変更で API が壊れることを防ぎます。
コミュニティが準備できたら、Strict TypeScript API をデフォルト API にして deep imports の削除と同期させます。将来に備えて今からオプトインを始めることを推奨します。
tsconfig.json の例:
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
...
"customConditions": ["react-native-strict-api"]
}
}
内部ではこれは TypeScript に対して、従来の types/ ディレクトリではなく types_generated/ ディレクトリから react-native の型を解決するよう指示します。TypeScript やエディタの再起動は不要です。
破壊的変更: Deep imports の無効化
Strict TypeScript API 下では型は main の react-native インポートパスからのみ解決可能になり、パッケージのカプセル化が強制されます。
// Before - import from subpath
import { Alert } from 'react-native/Libraries/Alert/Alert';
// After - MUST import from `react-native`
import { Alert } from 'react-native';
主な利点
公開 API を React Native の index.js のエクスポートに範囲限定したため、コードベースの他のファイルの変更が破壊的変更にならなくなります。
破壊的変更: 一部の型名/型形状の変更
型は手動で維持されるのではなくソースから生成されます。これにより以下を行いました:
- コミュニティ寄稿型に蓄積していた差異を整合させた。
- 型のカバレッジを増やした。
- 単純化や曖昧さ低減の余地がある型名や型形状は意図的に更新した。
利点
型が React Native のソースから生成されるため、あるバージョンの react-native に対して型チェッカーが常に正確であると確信できます。
例:より厳密なエクスポートシンボル
Linking API はこれまで 2 つのエクスポートでしたが、現在は単一のインターフェイスとなっています。これは他の多くの API にも適用されます(詳細は docs)。
import { Linking, LinkingStatic } from 'react-native';
function foo(linking: LinkingStatic) {}
foo(Linking);
import { Linking } from 'react-native';
function foo(linking: Linking) {}
foo(Linking);
例:修正/より完全な型
手動による以前の型定義は型の抜けが生じる余地がありました。Flow → TypeScript 生成ではこれらは解消され(かつソースでは Flow による追加の型検証の恩恵を受けます)。
import { Dimensions } from 'react-native';
const { densityDpi } = Dimensions.get();
その他の破壊的変更
破壊的な型の変更と更新方法の詳細は、ドキュメント内の専用ガイドを参照してください。
ロールアウト
我々は破壊的な変更が開発者に影響を与えることを理解しており、移行に時間がかかることを認識しています。
現在 — オプトイン開始(0.80)
react-native-strict-api のオプトインは 0.80 で安定しています。これは一度限りの移行です。
- アプリやライブラリは次の数回のリリースにかけて各自のペースでオプトインすることを想定しています。
- いずれのモードでもランタイムでの挙動は変わらず、TypeScript の解析のみに影響します。
- 欠落している API については専用のフィードバックスレッドで意見を受け付けます。
推奨
Strict TypeScript API は将来的にデフォルトになります。時間が取れる場合は今すぐ tsconfig.json でオプトインしてテストすることを推奨します。これにより Strict API で型エラーが発生するかを即座に評価できます。場合によっては何もエラーが出ないこともあります。
将来 — Strict TypeScript API をデフォルトに
将来的にはすべてのコードベースに Strict API の使用を必須化し、レガシー型を削除する予定です。タイムラインはコミュニティからのフィードバックに基づきます。少なくとも次の 2 回の React Native リリースでは Opt-in のままとします。
FAQ
フィードバックを歓迎します!
サブパス import の変更と同様、Strict API に関する統合問題があれば GitHub でお知らせください。
最終的な API を保証するものですか?
残念ながら現時点では最終確定ではありません。0.80 では tooling への投資を行い、既存の JS API ベースラインが TypeScript を通して正確に消費できるようにしました。これにより将来の安定化に向けた動作を可能にします。今後は各言語面で core が提供する API を最終化していき、RFC/発表と通常の非推奨サイクルを通じて通知します。
なぜ React Native は TypeScript で書かれていないのですか?
React Native は Meta のコアインフラストラクチャです。マージされた変更は Family of Apps 全体でテストされてから一般公開されます。その規模と機密性を考えると、正確性が重要であり、Flow は TypeScript よりも高いパフォーマンスとより厳格な検証、特にマルチプラットフォームサポートにおいて優れているためです。
謝辞
これらの変更は Iwo Plaza、Jakub Piasecki、Dawid Małecki、Alex Hunt、Riccardo Cipolleschi によって可能になりました。追加の助力・意見をくれた Pieter Vanderwerff、Rubén Norte、Rob Hogan にも感謝します。
詳しく学ぶ
Watch the talk! App.js 2025 で Strict TypeScript API に関する深掘りを共有しました。View on YouTube