Skip to main content

使用 TypeScript

TypeScript 是一种通过添加类型定义来扩展 JavaScript 的语言。新的 React Native 项目默认以 TypeScript 为目标,但也支持 JavaScript 和 Flow。

¥TypeScript is a language which extends JavaScript by adding type definitions. New React Native projects target TypeScript by default, but also support JavaScript and Flow.

TypeScript 入门

¥Getting Started with TypeScript

React Native CLI 或流行模板(如 Ignite)创建的新项目将默认使用 TypeScript。

¥New projects created by the React Native CLI or popular templates like Ignite will use TypeScript by default.

TypeScript 还可以与 Expo 一起使用,Expo 维护 TypeScript 模板,或者在将 .ts.tsx 文件添加到项目时提示你自动安装和配置 TypeScript。

¥TypeScript may also be used with Expo, which maintains TypeScript templates, or will prompt you to automatically install and configure TypeScript when a .ts or .tsx file is added to your project.

npx create-expo-app --template

将 TypeScript 添加到现有项目

¥Adding TypeScript to an Existing Project

  1. 将 TypeScript、类型和 ESLint 插件添加到你的项目中。

    ¥Add TypeScript, types, and ESLint plugins to your project.

npm install -D @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript
注意

此命令添加每个依赖的最新版本。可能需要更改版本以匹配项目使用的现有包。你可以使用 React Native 升级助手 这样的工具来查看 React Native 发布的版本。

¥This command adds the latest version of every dependency. The versions may need to be changed to match the existing packages used by your project. You can use a tool like React Native Upgrade Helper to see the versions shipped by React Native.

  1. 添加 TypeScript 配置文件。在项目的根目录中创建 tsconfig.json

    ¥Add a TypeScript config file. Create a tsconfig.json in the root of your project:

{
"extends": "@tsconfig/react-native/tsconfig.json"
}
  1. 将 JavaScript 文件重命名为 *.tsx

    ¥Rename a JavaScript file to be *.tsx

你应该保留 ./index.js 入口点文件,否则在打包生产构建时可能会遇到问题。

¥You should leave the ./index.js entrypoint file as it is otherwise you may run into an issue when it comes to bundling a production build.

  1. 运行 tsc 对新的 TypeScript 文件进行类型检查。

    ¥Run tsc to type-check your new TypeScript files.

npx tsc

使用 JavaScript 代替 TypeScript

¥Using JavaScript Instead of TypeScript

React Native 默认新应用使用 TypeScript,但仍可以使用 JavaScript。带有 .jsx 扩展名的文件被视为 JavaScript 而不是 TypeScript,并且不会进行类型检查。JavaScript 模块仍可以由 TypeScript 模块导入,反之亦然。

¥React Native defaults new applications to TypeScript, but JavaScript may still be used. Files with a .jsx extension are treated as JavaScript instead of TypeScript, and will not be typechecked. JavaScript modules may still be imported by TypeScript modules, along with the reverse.

TypeScript 和 React Native 的工作原理

¥How TypeScript and React Native works

开箱即用,TypeScript 源在打包期间由 Babel 进行转换。我们建议你仅使用 TypeScript 编译器进行类型检查。这是 tsc 对于新创建的应用的默认行为。如果你将现有的 TypeScript 代码移植到 React Native,则需要使用 Babel 而不是 TypeScript。

¥Out of the box, TypeScript sources are transformed by Babel during bundling. We recommend that you use the TypeScript compiler only for type checking. This is the default behavior of tsc for newly created applications. If you have existing TypeScript code being ported to React Native, there are one or two caveats to using Babel instead of TypeScript.

React Native + TypeScript 是什么样子的

¥What does React Native + TypeScript look like

你可以通过 React.Component<Props, State> 为 React 组件的 属性状态 提供一个接口,这将在 JSX 中使用该组件时提供类型检查和编辑器自动补齐功能。

¥You can provide an interface for a React Component's Props and State via React.Component<Props, State> which will provide type-checking and editor auto-completing when working with that component in JSX.

components/Hello.tsx
import React from 'react';
import {Button, StyleSheet, Text, View} from 'react-native';

export type Props = {
name: string;
baseEnthusiasmLevel?: number;
};

const Hello: React.FC<Props> = ({
name,
baseEnthusiasmLevel = 0,
}) => {
const [enthusiasmLevel, setEnthusiasmLevel] = React.useState(
baseEnthusiasmLevel,
);

const onIncrement = () =>
setEnthusiasmLevel(enthusiasmLevel + 1);
const onDecrement = () =>
setEnthusiasmLevel(
enthusiasmLevel > 0 ? enthusiasmLevel - 1 : 0,
);

const getExclamationMarks = (numChars: number) =>
numChars > 0 ? Array(numChars + 1).join('!') : '';

return (
<View style={styles.container}>
<Text style={styles.greeting}>
Hello {name}
{getExclamationMarks(enthusiasmLevel)}
</Text>
<View>
<Button
title="Increase enthusiasm"
accessibilityLabel="increment"
onPress={onIncrement}
color="blue"
/>
<Button
title="Decrease enthusiasm"
accessibilityLabel="decrement"
onPress={onDecrement}
color="red"
/>
</View>
</View>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
greeting: {
fontSize: 20,
fontWeight: 'bold',
margin: 16,
},
});

export default Hello;

你可以在 TypeScript 在线运行 中更多地探索语法。

¥You can explore the syntax more in the TypeScript playground.

哪里可以找到有用的建议

¥Where to Find Useful Advice

将自定义路径别名与 TypeScript 结合使用

¥Using Custom Path Aliases with TypeScript

要在 TypeScript 中使用自定义路径别名,你需要将路径别名设置为同时在 Babel 和 TypeScript 中使用。就是这样:

¥To use custom path aliases with TypeScript, you need to set the path aliases to work from both Babel and TypeScript. Here's how:

  1. 编辑你的 tsconfig.json 以获取 自定义路径映射。将 src 根目录中的任何内容设置为可用,无需前面的路径引用,并允许使用 tests/File.tsx 访问任何测试文件:

    ¥Edit your tsconfig.json to have your custom path mappings. Set anything in the root of src to be available with no preceding path reference, and allow any test file to be accessed by using tests/File.tsx:

{
- "extends": "@tsconfig/react-native/tsconfig.json"
+ "extends": "@tsconfig/react-native/tsconfig.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "*": ["src/*"],
+ "tests": ["tests/*"],
+ "@components/*": ["src/components/*"],
+ },
+ }
}
  1. babel-plugin-module-resolver 作为开发包添加到你的项目中:

    ¥Add babel-plugin-module-resolver as a development package to your project:

npm install --save-dev babel-plugin-module-resolver
  1. 最后,配置 babel.config.js(请注意,babel.config.js 的语法与 tsconfig.json 不同):

    ¥Finally, configure your babel.config.js (note that the syntax for your babel.config.js is different from your tsconfig.json):

{
presets: ['module:metro-react-native-babel-preset'],
+ plugins: [
+ [
+ 'module-resolver',
+ {
+ root: ['./src'],
+ extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
+ alias: {
+ tests: ['./tests/'],
+ "@components": "./src/components",
+ }
+ }
+ ]
+ ]
}