使用 TypeScript
TypeScript is a language which extends JavaScript by adding type definitions, much like Flow. While React Native is built in Flow, it supports both TypeScript and Flow by default.
使用 TypeScript 开始新项目
如果您要开始一个新项目,则 有几种不同的上手方法。 您可以使用TypeScript 模板:
npx react-native init MyApp --template react-native-template-typescript
Note 如果以上命令失败,则可能是您的 PC 上全局安装了旧版本的
react-native
或react-native-cli
。 尝试卸载 cli 并使用npx
运行 cli.
您可以使用具有两个 TypeScript 模板的Expo:
npm install -g expo-cli
expo init MyTSProject
或者,您可以使用Ignite,它也具有 TypeScript 模板:
npm install -g ignite-cli
ignite new MyTSProject
在已有的 项目中添加 TypeScript
- 将 TypeScript 以及 React Native 和 Jest 的依赖添加到您的项目中。
yarn add --dev typescript @types/jest @types/react @types/react-native @types/react-test-renderer
# or for npm
npm install --save-dev typescript @types/jest @types/react @types/react-native @types/react-test-renderer
添加一个 TypeScript 配置文件。在项目的根目录中创建一个tsconfig.json
:
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"jsx": "react-native",
"lib": ["es2017"],
"types": ["react-native", "jest"],
"moduleResolution": "node",
"noEmit": true,
"strict": true,
"target": "esnext"
},
"exclude": [
"node_modules",
"babel.config.js",
"metro.config.js",
"jest.config.js"
]
}
- 创建一个
jest.config.js
文件来配置 Jest 以使用 TypeScript:
module.exports = {
preset: 'react-native',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node']
};
- 将 JavaScript 文件重命名为
* .tsx
:
请保留
./index.js
入口文件,否则将在打包生产版本时遇到问题。
- 运行
yarn tsc
对 TypeScript 文件进行类型检查。
TypeScript 和 React Native 是如何工作的
无需额外配置,和非 TypeScript 的 React Native 项目一样都是直接通过 Babel 体系 将您的文件转换为 JavaScript。我们建议您只使用 TypeScript 编译器的类型检查功能(而不是编译)。如果您有已经存在的 TypeScript 代码需要迁移到 React Native,这里有一些关于使用 Babel 而不是 TypeScript 编译器的注意事项。
用 TypeScript 写 React Native 的示例
可以用interface
来为 React 的函数组件编写Props的类型(使用React.FC<Props>
)。这样在后续编码的过程中,编辑器就会根据这一类型来做类型检查并提供自动补全。
// components/Hello.tsx
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
export interface Props {
name: string;
enthusiasmLevel?: number;
}
const Hello: React.FC<Props> = (props) => {
const [enthusiasmLevel, setEnthusiasmLevel] = React.useState(
props.enthusiasmLevel
);
const onIncrement = () =>
setEnthusiasmLevel((enthusiasmLevel || 0) + 1);
const onDecrement = () =>
setEnthusiasmLevel((enthusiasmLevel || 0) - 1);
const getExclamationMarks = (numChars: number) =>
Array(numChars + 1).join('!');
return (
<View style={styles.root}>
<Text style={styles.greeting}>
Hello{' '}
{props.name + getExclamationMarks(enthusiasmLevel || 0)}
</Text>
<View style={styles.buttons}>
<View style={styles.button}>
<Button
title="-"
onPress={onDecrement}
accessibilityLabel="decrement"
color="red"
/>
</View>
<View style={styles.button}>
<Button
title="+"
onPress={onIncrement}
accessibilityLabel="increment"
color="blue"
/>
</View>
</View>
</View>
);
};
// styles
const styles = StyleSheet.create({
root: {
alignItems: 'center',
alignSelf: 'center'
},
buttons: {
flexDirection: 'row',
minHeight: 70,
alignItems: 'stretch',
alignSelf: 'center',
borderWidth: 5
},
button: {
flex: 1,
paddingVertical: 0
},
greeting: {
color: '#999',
fontWeight: 'bold'
}
});
export default Hello;
You can explore the syntax more in the TypeScript playground.
参考资料(英文)
在 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:
- Edit your
tsconfig.json
to have your custom path mappings. Set anything in the root ofsrc
to be available with no preceding path reference, and allow any test file to be accessed by usingtest/File.tsx
:
"target": "esnext",
+ "baseUrl": ".",
+ "paths": {
+ "*": ["src/*"],
+ "tests": ["tests/*"],
+ "@components/*": ["src/components/*"],
+ },
}
- Configure the Babel side done by adding a new dependency,
babel-plugin-module-resolver
:
yarn add --dev babel-plugin-module-resolver
# or
npm install --save-dev babel-plugin-module-resolver
- Finally, configure your
babel.config.js
(note that the syntax for yourbabel.config.js
is different from yourtsconfig.json
):
{
plugins: [
+ [
+ 'module-resolver',
+ {
+ root: ['./src'],
+ extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
+ alias: {
+ "tests": ["./tests/"],
+ "@components": "./src/components",
+ }
+ }
+ ]
]
}