本文根据日常开发实践,参考优秀文章、文档,来说说 TypeScript
是如何较优雅的融入 React
项目的。
温馨提示:日常开发中已全面拥抱函数式组件和 React Hooks
,class
类组件的写法这里不提及。
前沿
- 以前有 JSX 语法,必须引入 React。React 17.0+ 不需要强制声明 React 了。
import React, {
useState } from 'react';
// 以后将被替代成
import {
useState } from 'react';
import * as React from 'react';
基础介绍
基本类型
- 基础类型就没什么好说的了,以下都是比较常用的,一般比较好理解,也没什么问题。
type BasicTypes = {
message: string;
count: number;
disabled: boolean;
names: string[]; // or Array<string>
id: string | number; // 联合类型
}
联合类型
一般的联合类型,没什么好说的,这里提一下非常有用,但新手经常遗忘的写法 —— 字符字面量联合。
- 例如:自定义
ajax
时,一般method
就那么具体的几种:get
、post
、put
等。
大家都知道需要传入一个string
型,你可能会这么写:
type UnionsTypes = {
method: string; // ❌ bad,可以传入任意字符串
};
- 使用字符字面量联合类型,第一、可以智能提示你可传入的字符常量;第二、防止拼写错误。后面会有更多的例子。
type UnionsTypes = {
method: 'get' | 'post'; // ✅ good 只允许 'get'、'post' 字面量
};
对象类型
- 一般你知道确切的属性类型,这没什么好说的。
type ObjectTypes = {
obj3: {
id: string;
title: string;
};
objArr: {
id: string;
title: string;
}[]; // 对象数组,or Array<{ id: string, title: string }>
};
- 但有时你只知道是个对象,而不确定具体有哪些属性时,你可能会这么用:
type ObjectTypes = {
obj: object; // ❌ bad,不推荐
obj2: {
}; // ❌ bad 几乎类似 object
};
- 一般编译器会提示你,不要这么使用,推荐使用
Record
。
type ObjectTypes = {
objBetter: Record<string, unknown>; // ✅ better,代替 obj: object
// 对于 obj2: {}; 有三种情况:
obj2Better1: Record<string, unknown>; // ✅ better 同上
obj2Better2: unknown; // ✅ any value
obj2Better3: Record<string, never>; // ✅ 空对象
/** Record 更多用法 */
dict1: {
[key: string]: MyTypeHere;
};
dict2: Record<string, MyTypeHere>; // 等价于 dict1
};
Record
有什么好处呢,先看看实现:
// 意思就是,泛型 K 的集合作为返回对象的属性,且值类型为 T
type Record<K extends keyof any, T> = {
[P in K]: T;
};
- 官方的一个例子
interface PageInfo {
title: string;
}
type Page = 'home' | 'about' | 'contact';
const nav: Record<Page, PageInfo> = {
about: {
title: 'about' },
contact: {
title: 'contact' },
// TS2322: Type '{ about: { title: string; }; contact: { title: string; }; hoem: { title: string; }; }'
// is not assignable to type 'Record<Page, PageInfo>'. ...
hoem: {
title: 'home' },
};
nav.about;
好处:
- 当你书写
home
值时,键入h
常用的编辑器有智能补全提示; home
拼写错误成hoem
,会有错误提示,往往这类错误很隐蔽;- 收窄接收的边界。
相关React实战视频讲解:进入学习
函数类型
- 函数类型不建议直接给
Function
类型,有明确的参数类型、个数与返回值类型最佳。
type FunctionTypes = {
onSomething: Function; // ❌ bad,不推荐。任何可调用的函数
onClick: () => void; // ✅ better ,明确无参数无返回值的函数
onChange: (id: number) => void; // ✅ better ,明确参数无返回值的函数
onClick(event: React.MouseEvent<HTMLButtonElement>): void; // ✅ better
};
可选属性
- React props 可选的情况下,比较常用。
type OptionalTypes = {
optional?: OptionalType; // 可选属性
};
- 例子:封装一个第三方组件,对方可能并没有暴露一个 props 类型定义时,而你只想关注自己的上层定义。
name
,age
是你新增的属性,age
可选,other
为第三方的属性集。
type AppProps = {
name: string;
age?: number;
[propName: string]: any;
};
const YourComponent = ({
name, age, ...other }: AppProps) => (
<div>
{
`Hello, my name is ${
name}, ${
age || 'unknown'}`<