Skip to main content

严格的 TypeScript API(选择加入)

Strict TypeScript API 是我们未来为 React Native 提供的稳定 JavaScript API 的预览版。

¥The Strict TypeScript API is a preview of our future, stable JavaScript API for React Native.

具体来说,这是针对 react-native npm 包的一组新 TypeScript 类型,从 0.80 开始可用。这些 API 提供了更强大、更面向未来的类型准确性,并使我们能够自信地将 React Native 的 API 演进到稳定的状态。选择严格的 TypeScript API 会带来一些结构类型的差异,因此这只是一次性的重大变更。

¥Specifically, this is a new set of TypeScript types for the react-native npm package, available from 0.80 onwards. These provide stronger and more futureproof type accuracy, and will allow us to confidently evolve React Native's API into a stable shape. Opting in to the Strict TypeScript API brings some structural type differences, and is therefore a one-time breaking change.

新类型为:

¥The new types are:

  1. 直接从我们的源代码生成 - 提升覆盖率和正确性,因此你可以期待更强的兼容性保证。

    ¥Generated directly from our source code — improving coverage and correctness, so you can expect stronger compatibility guarantees.

  2. 仅限于 react-native 的索引文件 - 更严格地定义我们的公共 API,这意味着我们在进行内部文件更改时不会破坏 API。

    ¥Restricted to react-native's index file — more tightly defining our public API, and meaning we won't break the API when making internal file changes.

当社区准备就绪后,Strict TypeScript API 将成为我们未来的默认 API - 并与深度导入移除同步。

¥When the community is ready, the Strict TypeScript API will become our default API in future — synchronized with deep imports removal.

选择加入

¥Opting in

我们将与现有类型一起提供这些新类型,这意味着你可以在准备就绪时选择迁移。我们鼓励早期采用者和新创建的应用通过你的 tsconfig.json 文件选择加入。

¥We're shipping these new types alongside our existing types, meaning you can choose to migrate when ready. We encourage early adopters and newly created apps to opt in via your tsconfig.json file.

选择加入是一项重大变更,因为我们的一些新类型已更新名称和形状,但许多应用不会受到影响。你可以在下一节中了解每个重大变更。

¥Opting in is a breaking change, since some of our new types have updated names and shapes, although many apps won't be affected. You can learn about each breaking change in the next section.

tsconfig.json
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
...
"customConditions": ["react-native-strict-api"]
}
}
底层原理

这将指示 TypeScript 从新的 types_generated/ 目录解析 react-native 类型,而不是之前的 types/ 目录(手动维护)。无需重启 TypeScript 或编辑器。

¥This will instruct TypeScript to resolve react-native types from our new types_generated/ dir, instead of the previous types/ dir (manually maintained). No restart of TypeScript or your editor is required.

Strict TypeScript API 遵循我们的 RFC,移除了 React Native 的深度导入。因此,某些 API 不再以根目录导出。这是有意为之,旨在减少 React Native API 的整体使用面积。

¥The Strict TypeScript API follows our RFC to remove deep imports from React Native. Therefore, some APIs are no longer exported at root. This is intentional, in order to reduce the overall surface area of React Native's API.

API 反馈

发送反馈:我们将与社区合作,最终确定我们将在接下来的两个 React Native 版本中(至少)导出哪些 API。请在我们的 反馈帖 中分享你的反馈。

¥Sending feedback: We will be working with the community to finalize which APIs we export over (at least) the next two React Native releases. Please share your feedback in our feedback thread.

另请参阅我们的 公告博文,了解更多关于我们动机和时间表的信息。

¥See also our announcement blog post for more info on our motivation and timelines.

迁移指南

¥Migration guide

现在应从 react-native 包导入 Codegen 类型

¥Codegen types should now be imported from the react-native package

用于代码生成的类型,例如 Int32DoubleWithDefault 等,现在可以在单个 CodegenTypes 命名空间下使用。同样,现在可以从 react-native 包中导入 codegenNativeComponentcodegenNativeCommands,而无需使用深度导入。

¥Types used for codegen, like Int32, Double, WithDefault etc. are now available under a single CodegenTypes namespace. Similarly, codegenNativeComponent and codegenNativeCommands are now available to import from the react-native package instead of using the deep import.

当未启用 Strict API 时,命名空间 CodegenTypescodegenNativeCommandscodegenNativeComponent 也可从 react-native 包中使用,以便第三方库更容易采用。

¥Namespaced CodegenTypes as well as codegenNativeCommands and codegenNativeComponent are also available from react-native package when the Strict API is not enabled to make the adoption easier for third-party libraries.

修改前

¥Before

import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type {
Int32,
WithDefault,
} from 'react-native/Libraries/Types/CodegenTypes';

interface NativeProps extends ViewProps {
enabled?: WithDefault<boolean, true>;
size?: Int32;
}

export default codegenNativeComponent<NativeProps>(
'RNCustomComponent',
);

修改后

¥After

import {CodegenTypes, codegenNativeComponent} from 'react-native';

interface NativeProps extends ViewProps {
enabled?: CodegenTypes.WithDefault<boolean, true>;
size?: CodegenTypes.Int32;
}

export default codegenNativeComponent<NativeProps>(
'RNCustomComponent',
);

移除 *Static 类型

¥Removal of *Static types

修改前

¥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);

以下 API 之前均以 *Static 加上同类型的变量声明命名。在大多数情况下,都有一个别名,以便值和类型在同一个标识符下导出,但有些情况缺失。

¥The following APIs were previously named as *Static plus a variable declaration of said type. In most cases there was an alias so that value and the type were exported under the same identifier, but some were missing.

(例如,存在 AlertStatic 类型、AlertStatic 类型的 Alert 变量以及 AlertStatic 的别名类型 Alert。但在 PixelRatio 的情况下,存在 PixelRatioStatic 类型和该类型的 PixelRatio 变量,但没有其他类型别名。)

¥(For example there was an AlertStatic type, Alert variable of type AlertStatic and type Alert which was an alias for AlertStatic. But in the case of PixelRatio there was a PixelRatioStatic type and a PixelRatio variable of that type without additional type aliases.)

受影响的 API

¥Affected APIs

  • AlertStatic

  • ActionSheetIOSStatic

  • ToastAndroidStatic

  • InteractionManagerStatic(在这种情况下,没有相关的 InteractionManager 类型别名)

    ¥InteractionManagerStatic (In this case there was no relevant InteractionManager type alias)

  • UIManagerStatic

  • PlatformStatic

  • SectionListStatic

  • PixelRatioStatic(在这种情况下,没有相关的 PixelRatio 类型别名)

    ¥PixelRatioStatic (In this case there was no relevant PixelRatio type alias)

  • AppStateStatic

  • AccessibilityInfoStatic

  • ImageResizeModeStatic

  • BackHandlerStatic

  • DevMenuStatic(在这种情况下,没有相关的 DevMenu 类型别名)

    ¥DevMenuStatic (In this case there was no relevant DevMenu type alias)

  • ClipboardStatic

  • PermissionsAndroidStatic

  • ShareStatic

  • DeviceEventEmitterStatic

  • LayoutAnimationStatic

  • KeyboardStatic(在这种情况下,没有相关的 Keyboard 类型别名)

    ¥KeyboardStatic (In this case there was no relevant Keyboard type alias)

  • DevSettingsStatic(在这种情况下,没有相关的 DevSettings 类型别名)

    ¥DevSettingsStatic (In this case there was no relevant DevSettings type alias)

  • I18nManagerStatic

  • EasingStatic

  • PanResponderStatic

  • NativeModulesStatic(在这种情况下,没有相关的 NativeModules 类型别名)

    ¥NativeModulesStatic (In this case there was no relevant NativeModules type alias)

  • LogBoxStatic

  • PushNotificationIOSStatic

  • SettingsStatic

  • VibrationStatic

部分核心组件现在是函数组件,而不是类组件

¥Some core components are now function components instead of class components

  • View

  • Image

  • TextInput

  • Modal

  • Text

  • TouchableWithoutFeedback

  • Switch

  • ActivityIndicator

  • ProgressBarAndroid

  • InputAccessoryView

  • Button

  • SafeAreaView

由于此更改,访问这些视图的引用类型需要使用 React.ComponentRef<typeof View> 模式,该模式对类组件和函数组件均能正常工作,例如:

¥Due to this change, accessing ref types of these views requires using React.ComponentRef<typeof View> pattern which works as expected for both class and function components, e.g.:

const ref = useRef<React.ComponentRef<typeof View>>(null);

其他重大变更

¥Other breaking changes

动画类型的变更

¥Changes to Animated types

动画节点以前是基于其插值输出的泛型类型。现在,它们是具有通用 interpolate 方法的非泛型类型。

¥Animated nodes were previously generic types based on their interpolation output. Now, they are non-generic types with a generic interpolate method.

Animated.LegacyRef 不再可用。

¥Animated.LegacyRef is no longer available.

统一可选属性的类型

¥Unified types for optional props

在新类型中,每个可选的 prop 都将被类型化为 type | undefined

¥In the new types, every optional prop will be typed as type | undefined.

移除部分弃用的类型

¥Removal of some deprecated types

DeprecatedPropertiesAlias.d.ts 中列出的所有类型在 Strict API 下均无法访问。

¥All types listed in DeprecatedPropertiesAlias.d.ts are inaccessible under the Strict API.

移除剩余的组件属性

¥Removal of leftover component props

一些在类型定义中定义但组件未使用或缺少定义的属性已被移除(例如:Text 上的 lineBreakModeScrollView 上的 scrollWithoutAnimationTo、在 transform 数组之外定义的 transform 样式)。

¥Some properties that were defined in type definitions but were not used by the component or were lacking a definition were removed (for example: lineBreakMode on Text, scrollWithoutAnimationTo on ScrollView, transform styles defined outside of transform array).

之前可访问的私有类型助手函数现在可以移除

¥Previously accessible private type helpers may now be removed

由于之前类型定义的配置,所有已定义的类型都可以从 react-native 包中访问。这包括未明确导出的类型和仅供内部使用的辅助类型。

¥Due to the configuration of the previous type definitions, every defined type was accessible from the react-native package. This included types that were not explicitly exported and helper types that were only supposed to be used internally.

值得注意的例子是与 StyleSheet(如 RecursiveArrayRegisteredStyleFalsy)和 Animated(如 WithAnimatedArrayWithAnimatedObject)相关的类型。

¥Notable examples of this are types related to StyleSheet (like RecursiveArray, RegisteredStyle and Falsy) and Animated (like WithAnimatedArray and WithAnimatedObject).