メインコンテンツへスキップ

安定したJavaScript APIに向けて (0.80での新しい変更点)

·10分で読めます
Alex Hunt
Alex Hunt
ソフトウェアエンジニア @ Meta
Iwo Plaza
Iwo Plaza
ソフトウェアエンジニア @ Software Mansion
Jakub Piasecki
Jakub Piasecki
ソフトウェアエンジニア @ Software Mansion
Dawid Małecki
Dawid Małecki
ソフトウェアエンジニア @ Software Mansion

React Native 0.80では、React NativeのJavaScript APIに2つの重要な変更を導入します。それは、ディープインポートの非推奨化と、新しいStrict TypeScript APIです。これらは、APIを正確に定義し、ユーザーやフレームワークに信頼性の高い型安全を提供するための継続的な取り組みの一部です。

主なポイント

  • ディープインポートの非推奨化: 0.80から、react-nativeパッケージからのディープインポートに対して非推奨の警告を導入します。
  • オプトイン Strict TypeScript API: ソースからのTypeScript型と、TypeScriptの下での新しい公開APIベースラインに移行します。これにより、より強力で将来性のある型の正確性が実現し、一度限りの破壊的変更となります。プロジェクトのtsconfig.jsoncompilerOptionsからオプトインしてください。
  • 将来のReact NativeリリースでStrict TypeScript APIをデフォルトで有効にする前に、これらの変更が誰にとっても機能するように、時間をかけてコミュニティと協力していきます。

何が変わるのか、そしてその理由

React Nativeの公開JavaScript API、つまり'react-native'をインポートしたときに得られるものを改善し、安定させることに取り組んでいます。

これまで、私たちはこれを概算してきました。React NativeはFlowで作成されていますが、オープンソースコミュニティは長い間TypeScriptに移行しており、公開APIがどのように利用され、互換性が検証されているかを示しています。私たちの型は、(愛を込めて)コミュニティによって提供され、その後、コードベースにマージされ、整合性が取られてきました。しかし、これらは手動でのメンテナンスと自動化されたツールに依存しておらず、正確性のギャップが生じていました。

さらに、私たちの公開JS APIは、モジュールの境界に関してうまく定義されていませんでした。たとえば、内部の'react-native/Libraries/'のディープインポートはアプリのコードからアクセスできましたが、これらの内部を更新するたびに頻繁に変更される可能性がありました。

0.80では、ディープインポートを非推奨にし、TypeScriptで新しい生成されたAPIベースラインへのユーザーオプトインを導入することで、これらの問題に対処します。これをStrict TypeScript APIと呼んでいます。最終的には、これが将来的に安定したReact Native APIを提供するための基盤となります。

react-nativeからのディープインポートの非推奨化

本日、APIに加える主な変更は、ディープインポートの使用を非推奨にすることです(RFC)。ESLintとJSコンソールに警告が表示されます。値と型のディープインポートは、react-nativeのルートインポートに更新する必要があります。

// Before - import from subpath
import {Alert} from 'react-native/Libraries/Alert/Alert';

// After - import from `react-native`
import {Alert} from 'react-native';

この変更により、JavaScript APIの総表面積が固定されたエクスポートセットに削減され、将来のリリースで制御可能かつ安定させることができます。これらのインポートパスは0.82で削除することを目指しています。

APIフィードバック

一部のAPIはルートでエクスポートされておらず、ディープインポートなしでは利用できなくなります。オープンなフィードバックスレッドがあり、公開APIのエクスポートを確定するためにコミュニティと協力していきます。ぜひフィードバックをお寄せください!

オプトアウト

将来のリリースでReact NativeのAPIからディープインポートを削除することを目指しているため、これらはルートインポートに更新する必要があることを念頭に置いてください。

警告のオプトアウト

ESLint

overridesを使用してno-deep-importsルールを無効にします。

.eslintrc.js
  overrides: [
{
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
rules: {
'@react-native/no-deep-imports': 0,
},
},
]

コンソール警告

disableDeepImportWarningsオプションを@react-native/babel-presetに渡します。

babel.config.js
module.exports = {
presets: [
['module:@react-native/babel-preset', {disableDeepImportWarnings: true}]
],
};

Metroキャッシュをクリアするために、--reset-cacheでアプリを再起動します。

npx @react-native-community/cli start --reset-cache
警告のオプトアウト(Expo)

ESLint

overridesを使用してno-deep-importsルールを無効にします。

.eslintrc.js
overrides: [
{
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
rules: {
'@react-native/no-deep-imports': 0,
},
},
];

コンソール警告

disableDeepImportWarningsオプションをbabel-preset-expoに渡します。

babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: [['babel-preset-expo', {disableDeepImportWarnings: true}]],
};
};

Metroキャッシュをクリアするために、--clearでアプリを再起動します。

npx expo start --clear

Strict TypeScript API(オプトイン)

Strict TypeScript APIは、react-nativeパッケージ内の新しいTypeScript型のセットであり、tsconfig.jsonを介してオプトインできます。既存のTS型と一緒にこれらを提供しており、準備ができたときに移行を選択できます。

新しい型は以下の通りです

  1. ソースコードから直接生成されます — カバレッジと正確性を向上させ、より強力な互換性保証を期待できます。
  2. react-nativeのインデックスファイルに制限されます — 公開APIをより厳密に定義し、内部ファイル変更時にAPIを破壊しないことを意味します。

コミュニティの準備ができたとき、Strict TypeScript APIは将来的にデフォルトのAPIとなり、ディープインポートの削除と同期されます。つまり、React Nativeの将来の安定したJS APIに備えるために、今からオプトインを開始することは良い考えです。

tsconfig.json
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
...
"customConditions": ["react-native-strict-api"]
}
}
内部的な仕組み

これにより、TypeScriptは以前のtypes/ディレクトリ(手動でメンテナンスされていた)ではなく、新しいtypes_generated/ディレクトリからreact-nativeの型を解決するように指示されます。TypeScriptやエディタを再起動する必要はありません。

破壊的変更: ディープインポートは許可されません

上記のとおり、Strict TypeScript APIの下での型は、上記の非推奨化に従い、パッケージのカプセル化を強制するために、メインの'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つのエクスポートではなく、単一のinterfaceになりました。これは、他の多くのAPIにも当てはまります(ドキュメントを参照)。

// Before
import {Linking, LinkingStatic} from 'react-native';

function foo(linking: LinkingStatic) {}
foo(Linking);

// After
import {Linking} from 'react-native';

function foo(linking: Linking) {}
foo(Linking);

例: 修正された/より完全な型

以前の手動での型定義では、型のギャップが生じる可能性がありました。Flow → TypeScriptで生成されるようになり、これらのギャップはなくなりました(そして、ソースでは、マルチプラットフォームコードに対するFlowの追加の型検証の恩恵を受けています)。

import {Dimensions} from 'react-native';

// Before - Type error
// After - number | undefined
const {densityDpi} = Dimensions.get();

その他の破壊的変更

すべての破壊的型変更とコードの更新方法については、ドキュメントの専用ガイドを参照してください。

ロールアウト

React Nativeへの破壊的変更が、開発者がアプリで更新するのに時間がかかることを理解しています。

現在 — オプトインの開始 (0.80)

"react-native-strict-api"オプトインは、0.80リリースで安定しています。

  • これは一度限りの移行です。アプリやライブラリが次のいくつかのリリースで独自のペースでオプトインすることを目指しています。
  • どちらのモードでも、実行時にアプリに変更はありません。これはTypeScriptの分析のみに影響します。
  • そして、不足しているAPIについては、専用のフィードバックスレッドを通じてフィードバックを収集します。
推奨

Strict TypeScript APIは、将来的にデフォルトのAPIとなります。

時間がある場合は、アプリやライブラリを将来にわたって対応させるために、今すぐtsconfig.jsonでオプトインを試してみる価値があります。これにより、Strict APIの下でアプリに型エラーが導入されるかどうかをすぐに評価できます。エラーがまったくない場合もあります(!) — その場合は、問題ありません。

将来 — Strict TypeScript APIがデフォルトに

将来、すべてのコードベースでStrict APIの使用を必須とし、レガシー型を削除します。

これのタイムラインはコミュニティのフィードバックに基づきます。少なくとも次の2つのReact Nativeリリースでは、Strict APIはオプトインのままとなります。

よくある質問

現在サブパスインポートを使用しています。どうすればよいですか?

ルートの'react-native'インポートパスに移行してください。

  • サブパスインポート(例:'react-native/Libraries/Alert/Alert')はプライベートAPIになりつつあります。React Native内部の実装ファイルへのアクセスを妨げなければ、安定したJavaScript APIを提供することはできません。
  • 非推奨警告はコミュニティのフィードバックを促すことを目的としています。アプリにとって不可欠なコードパスが公開されていないと思われる場合は、中央の議論スレッドを通じてフィードバックを提起できます。正当な場合は、APIをインデックスエクスポートに昇格させる可能性があります。

私はライブラリのメンテナーです。この変更は私にどう影響しますか?

tsconfig.jsonは直接のコードベースのみに影響するため、アプリとライブラリの両方で自分のペースでオプトインできます。

  • 通常、React Nativeプロジェクトでは、node_modulesはTypeScriptサーバーによる検証から除外されます。したがって、パッケージのエクスポートされた型定義が信頼できる情報源となります。

💡 フィードバックを募集しています! 変更されたサブパスインポートと同様に、Strict APIとの統合で問題が発生した場合は、GitHubでお知らせください。

これでReact Nativeの最終的なAPIが保証されますか?

残念ながら、まだです。0.80では、React Nativeの既存のJS APIベースラインをTypeScriptを介して正確に利用できるようにするためのツール開発に投資しました。これにより、将来の安定した変更が可能になります。現在、ご存知の既存のAPIを形式化しています。

将来、コアで現在提供しているAPIを各言語サーフェス全体で確定するための措置を講じます。APIの変更は、RFC/アナウンス、そして通常は非推奨サイクルを介して伝えられます。

React NativeはなぜTypeScriptで書かれていないのですか?

React NativeはMetaのコアインフラストラクチャです。私たちは、一般にオープンソースで利用可能になる前に、マージされたすべての変更をファミリーオブアプリ全体でテストしています。

この規模と機密性では、正確性が重要です。結論として、Flowは、React Nativeの特定のマルチプラットフォームサポートを含め、TypeScriptよりも優れたパフォーマンスと厳密性を提供します。

謝辞

これらの変更は、Iwo PlazaJakub PiaseckiDawid MałeckiAlex HuntRiccardo Cipolleschiの尽力により実現しました。

Pieter VanderwerffRubén NorteRob Hoganの追加の協力とご意見にも感謝いたします。

もっと学ぶ
講演をご覧ください!App.js 2025で、Strict TypeScript APIの背後にある動機と作業について詳細な説明を共有しました。

YouTubeで視聴する

App.js 2025 Talk