TS速成day4

133 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天

映射类型

映射类型:基于旧类型创建新类型(对象类型),减少重复、提升开发效率。

比如,类型PropKeys有x/y/z,另一个类型Type1中也有x/y/z,并且Type1中x/y/z的类型相同:

type PropKeys = 'x' | 'y' | 'z'
type Type1 = {x: number; y: number; z: number }

这样书写没错,但x/y/z重复书写了两次。像这种情况,就可以使用映射类型来进行简化。

type PropKeys = 'x' | 'y' | 'z'
type Type2 = { [Key in PropKeys]: number }

解释:

1.映射类型是基于索引签名类型的,所以,该语法类似于索引签名类型,也使用了[]。

2.Key in PropKeys表示Key可以是PropKeys联合类型中的任意一个,类似于forin(let k in obj)

3.使用映射类型创建的新对象类型 Type2 和类型 Type1 结构完全相同。

4. 注意:映射类型只能在类型别名中使用,不能在接口中使用。

映射类型除了根据联合类型创建新类型外,还可以根据对象类型来创建:

type Props = { a: number; b: string; c: boolean }
type Type3 = { [key in keyof Props]: number }

解释:

1. 首先,先执行 keyof Props 获取到对象类型 Props中所有键的联合类型即,'a'|'b' |'c'。

2.然后, Key in ... 就表示 Key可以是 Props中所有的键名称中的任意一个。

实际上,前面讲到的泛型工具类型(比如, Partial)都是基于映射类型实现的。

比如, Partial的实现:

解释:

1. keyof T即 keyof Props表示获取Props的所有键,也就是: 'a'l'b' |'c'。

2. 在]后面添加?(问号),表示将这些属性变为可选的,以此来实现Partial的功能。

3. 冒号后面的T[P]表示获取T中每个键对应的类型。比如,如果是'a'则类型是number;如果是'b'则类型是string。

4. 最终,新类型PartialProps和旧类型Props结构完全相同,只是让所有类型都变为可选了。

索引查询类型

刚刚用到的T[P] 语法,在TS 中叫做索引查询(访问)类型。

作用:用来查询属性的类型。

type Props = { a: number; b: string; c: boolean }
type TypeA = number
type TypeA = Props['a']

解释:Props['a']表示查询类型Props中属性'a'对应的类型number。所以,TypeA的类型为number。

注意:[]中的属性必须存在于被查询类型中,否则就会报错。

type Props = { a: number; b: string; c: boolean }
type TypeA = Props['a' | 'b'] // string 1 number

解释:使用字符串字面量的联合类型,获取属性a和b对应的类型,结果为:string | number。

type TypeA = Props[keyof Props]//string | number | boolean

解释:使用keyof操作符获取Props中所有键对应的类型,结果为: string | number | boolean

在React中使用TS

使用CRA创建支持TS的项目

React脚手架工具create-react-app (简称: CRA)默认支持TypeScript。

创建支持TS的项目命令: npx create-react-app项目名称--template typescript。

当看到以下提示时,表示支持TS 的项目创建成功:

在已有的项目中添加TS:

装完包要改文件名和重启服务器

目录结构说明

相对于非 TS 项目,目录结构主要由以下三个变化:

1. 项目根目录中增加了tsconfig.json配置文件:指定TS的编译选项(比如,编译时是否移除注释) 。

2. React组件的文件扩展名变为: *.tsx。

3. src目录中增加了react-app-env.d.ts: React项目默认的类型声明文件。

TS 配置文件react-app-env.d.ts

///<reference types="react-scripts" />

三斜线指令:指定依赖的其他类型声明文件,types表示依赖的类型声明文件包的名称。

解释:告诉 TS 帮我加载 react-scripts 这个包提供的类型声明。

react-scripts 的类型声明文件包含了两部分类型:

1. react, react-dom, node 的类型

2. 图片、样式等模块的类型,以允许在代码中导入图片、SVG等文件。

TS 会自动加载该.d.ts 文件,以提供类型声明(通过修改 tsconfig.json 中的 include 配置来验证)。

TS 配置文件tsconfig.json

tsconfig.json 指定:项目文件和项目编译所需的配置项。

注意:TS 的配置项非常多(100+),以CRA 项目中的配置为例来学习,其他的配置项用到时查文档即可。

1. tsconfig.json文件所在目录为项目根目录(与package.json同级) 。

2. tsconfig.json可以自动生成,命令: tsc--init。

除了在tsconfig.json文件中使用编译配置外,还可以通过命令行来使用。

使用演示:tsc hello.ts--target es6。

注意:

1.tsc后带有输入文件时(比如,tschello.ts),将忽略tsconfig.json文件。

2.tsc 后不带输入文件时(比如,tsc),才会启用 tsconfig.json。

推荐使用:tsconfig.json配置文件。

React中常用的类型

前提说明:现在,基于class组件来讲解React+TS的使用(最新的React Hooks,在后面讲解) 。

在不使用TS时,可以使用prop-types库,为React组件提供类型检查。

说明: TS项目中,推荐使用TypeScript实现组件类型校验(代替PropTypes)。

不管是 React 还是Vue,只要是支持 TS 的库,都提供了很多类型,来满足该库对类型的需求。

注意:

1. React项目是通过@types/react、@types/react-dom类型声明包,来提供类型的。

2. 这些包 CRA 已帮我们安装好(react-app-env.d.ts),直接用即可。

React是组件化开发模式,React开发主要任务就是写组件,两种组件:1函数组件2 class组件。

1.函数组件,主要包括以下内容:

组件的类型

组件的属性(props)

组件属性的默认值(defaultProps)

事件绑定和事件对象

函数组件的类型以及组件的属性

import ReactDOM from 'react-dom';
import {FC}from 'react'

type Props = { name: string; age?: number }

const Hello: FC<Props> = ({ name, age }) => (
  <div>你好,我叫:{name},我 {age} 岁了</div>)

<Hello name="jack" age={18} />//注意age传的是number,要用{}包裹

PS:FC是react提供的一种类型,是function-component的简写,并且FC是一个泛型,因此通过<>可以传入一个类型变量,这个类型变量就是用来指定组件能够接收的属性的

上面的代码意思是Hello组件可以接受name和age属性,并且age是可选项,这样后面渲染Hello组件name属性是必须要传的,age属性是可选的,同时Props还作为函数的参数类型,这样当要用到函数参数的时候就可以利用对象的解构来解构出那么和age属性,实际上函数组件的参数就是组件的props,接下来就可以在jsx中使用参数了。

const Hello =({name,age}:Props)=>(
<div>你好,我叫:{name},我{age}岁了</div>
)

这种方法没有用到react提供的FC类型,而是完全使用了TS自身的能力

这两种都可以用,但是个人喜欢用第二种

函数组件属性的默认值

const Hello:FC<Props> =({name,age_})=>(
<div>你好,我叫:{name},我{age}岁了<div>)
Hello.defaultProps ={
age:18
}

实际上,还可以直接简化为(完全按照函数在TS中的写法):

const Hello = (	{ name, age = 18 }: Props) => (
<div>你好,我叫:{name},我 {age} 岁了</div>)

事件绑定和事件对象

<button onClick={onClick}>点赞</button>

const onClick = () =>{}
const onClick1 = (e: React.MouseEvent<HTMLButtonElement>)=>{}

再比如,文本框:

<input onChange={onChange}
const onChange = (e: React. ChangeEvent<HTMLInputElement>)=>{}

技巧:在JSX中写事件处理程序(e=>{}),然后,把鼠标放在e上,利用TS的类型推论来查看事件对象类型。