严格的 TypeScript API(选择启用)
严格的 TypeScript API 是我们未来稳定版 React Native JavaScript API 的预览。
具体来说,这是一套适用于 react-native
npm 包的新 TypeScript 类型,从 0.80 版本起可用。这些类型提供了更强大、更面向未来的类型准确性,并将使我们能够自信地将 React Native 的 API 演变为稳定的形态。选择启用严格的 TypeScript API 会带来一些结构化的类型差异,因此这是一次性的破坏性变更。
新类型具有以下特点:
- 直接从我们的源代码生成 — 提高了覆盖率和正确性,因此您可以期待更强的兼容性保证。
- 仅限于
react-native
的 index 文件 — 更严格地定义了我们的公共 API,这意味着在进行内部文件更改时不会破坏 API。
当社区准备就绪时,严格的 TypeScript API 将在未来成为我们的默认 API — 与深度导入的移除同步进行。
选择启用
我们正在与现有类型一起发布这些新类型,这意味着您可以选择在准备好时进行迁移。我们鼓励早期采用者和新创建的应用通过您的 tsconfig.json
文件选择启用。
选择启用是一项破坏性变更,因为我们的一些新类型更新了名称和形状,尽管许多应用不会受到影响。您可以在下一节中了解每个破坏性变更。
{
"extends": "@react-native/typescript-config",
"compilerOptions": {
...
"customConditions": ["react-native-strict-api"]
}
}
这将指示 TypeScript 从我们新的 types_generated/
目录解析 react-native 类型,而不是以前的 types/
目录(手动维护)。无需重启 TypeScript 或您的编辑器。
严格的 TypeScript API 遵循我们的 RFC,以移除 React Native 中的深度导入。因此,一些 API 不再从根目录导出。这是有意为之的,目的是减少 React Native API 的整体表面积。
迁移指南
Codegen 类型现在应从 react-native
包导入
用于 Codegen 的类型,例如 Int32
、Double
、WithDefault
等,现在可在单个 CodegenTypes
命名空间下使用。类似地,codegenNativeComponent
和 codegenNativeCommands
现在可以从 react-native 包导入,而不是使用深度导入。
当未启用严格 API 时,带命名空间的 CodegenTypes
以及 codegenNativeCommands
和 codegenNativeComponent
也可从 react-native 包获取,以便第三方库更轻松地采用。
之前
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',
);
之后
import {CodegenTypes, codegenNativeComponent} from 'react-native';
interface NativeProps extends ViewProps {
enabled?: CodegenTypes.WithDefault<boolean, true>;
size?: CodegenTypes.Int32;
}
export default codegenNativeComponent<NativeProps>(
'RNCustomComponent',
);
移除 *Static
类型
之前
import {Linking, LinkingStatic} from 'react-native';
function foo(linking: LinkingStatic) {}
foo(Linking);
之后
import {Linking} from 'react-native';
function foo(linking: Linking) {}
foo(Linking);
以下 API 之前命名为 *Static
加上该类型的变量声明。在大多数情况下,存在一个别名,以便值和类型在同一标识符下导出,但有些缺失了。
(例如,之前有一个 AlertStatic
类型、一个 AlertStatic
类型的 Alert
变量,以及一个作为 AlertStatic
别名的 Alert
类型。但在 PixelRatio
的情况下,有一个 PixelRatioStatic
类型和一个该类型的 PixelRatio
变量,没有额外的类型别名。)
受影响的 API
AlertStatic
ActionSheetIOSStatic
ToastAndroidStatic
InteractionManagerStatic
(在这种情况下没有相关的InteractionManager
类型别名)UIManagerStatic
PlatformStatic
SectionListStatic
PixelRatioStatic
(在这种情况下没有相关的PixelRatio
类型别名)AppStateStatic
AccessibilityInfoStatic
ImageResizeModeStatic
BackHandlerStatic
DevMenuStatic
(在这种情况下没有相关的DevMenu
类型别名)ClipboardStatic
PermissionsAndroidStatic
ShareStatic
DeviceEventEmitterStatic
LayoutAnimationStatic
KeyboardStatic
(在这种情况下没有相关的Keyboard
类型别名)DevSettingsStatic
(在这种情况下没有相关的DevSettings
类型别名)I18nManagerStatic
EasingStatic
PanResponderStatic
NativeModulesStatic
(在这种情况下没有相关的NativeModules
类型别名)LogBoxStatic
PushNotificationIOSStatic
SettingsStatic
VibrationStatic
一些核心组件现在是函数组件而非类组件
View
Image
TextInput
Modal
Text
TouchableWithoutFeedback
Switch
ActivityIndicator
ProgressBarAndroid
InputAccessoryView
Button
SafeAreaView
由于此变更,访问这些视图的 ref 类型需要使用 React.ComponentRef<typeof View>
模式,该模式对于类组件和函数组件都如预期般工作,例如:
const ref = useRef<React.ComponentRef<typeof View>>(null);
其他破坏性变更
Animated 类型的变更
Animated 节点之前是基于其插值输出的泛型类型。现在,它们是非泛型类型,但具有一个泛型的 interpolate
方法。
Animated.LegacyRef
不再可用。
可选 props 的统一类型
在新类型中,每个可选 prop 都将被类型化为 type | undefined
。
移除部分已弃用的类型
在 DeprecatedPropertiesAlias.d.ts
中列出的所有类型在严格 API 下都无法访问。
移除遗留的组件 props
一些在类型定义中定义但组件未使用或缺少定义的属性已被移除(例如:Text
上的 lineBreakMode
,ScrollView
上的 scrollWithoutAnimationTo
,以及在 transform 数组之外定义的 transform 样式)。
之前可访问的私有类型辅助工具现在可能已被移除
由于之前的类型定义配置,每个定义的类型都可以从 react-native 包访问。这包括未明确导出的类型以及本应仅供内部使用的辅助类型。
值得注意的例子是与 StyleSheet 相关的类型(如 RecursiveArray
、RegisteredStyle
和 Falsy
)和与 Animated 相关的类型(如 WithAnimatedArray
和 WithAnimatedObject
)。