一. 前言
在日常开发中TypeScript已经很常见啦。但是我们真的可以很熟悉的、或者说很优雅的使用ts去声明一些类型么?如果你觉得还差那么一点点味道的话,可以跟着小美老师来了解一下哦。
二. 类型总结
2.1 ts内置类型
keyof
定义:
获取类型内的所有keys,获取的是一个由当前key组成的联合类型。
使用:
js
type Texample = {
x: number,
y: string
}
type Tkey = keyof Texample;
等同于:
type Tkey = x | y;
注意一下: typeof any
:
js
typeof any;
等同于:
type Tex = string | number | symbol
in操作符
遍历类型
遍历联合类型里面的每个key,把联合类型中每一个属性名赋值给 P
在这个例子里面: P就是属性,any就是类型。因为unions里面有三个属性,所以TExuni里面也有三个属性,类型都为any
extends
extends
是 ts 里一个很常见的关键字,日常中的使用比较多
- 继承基本用法
A extends B
(A类型继承于B类型)
js
type Ex1 = {
name: string,
age: number
}
interface Ex2 extends Ex1 {}
- 继承的扩展
js
type Ex1 = {
name: string,
age: number
}
interface Ex2 extends Ex1 {}
// 在继承的同时,可以自己扩展属性。
export interface Ex3 extends Ex2 {
value: string
}
- 类型的分配
extends还有一用途就是用来判断一个类型是不是可以分配给另一个类型
SomeType extends OtherType ? TrueType : FalseType;
extends
举个例子:
js
type Ex1 = {
name: string
}
type Ex2 = {
name: string
}
type Ex3 = Ex1 extends Ex2 ? 'yes' : 'no' // type Ex3 = "yes"
注意: 这里的Ex1 extends Ex2
,是指类型Ex1
可以分配给类型Ex2
,而不是说类型Ex1
是类型Ex2
的子集
js
type Ex1 = {
name: string,
age: number
}
type Ex2 = {
name: string
}
type Ex3 = Ex1 extends Ex2 ? 'yes' : 'no'
// 这里Ex1有两个属性,Ex2有一个属性(这个属性包含在Ex1里面)Ex1可以把类型分配给Ex2
Pick<Type, Keys>
从 Type 类型中选取部分 Keys,并返回新的类型,这里 Type类型 常用于对象类型
js
type Pick<T, K extends keyof T> = {
[P in K]: T[p]
}
// keyof T 获取T中的所有类型
// K extends keyof T K继承T
// P in K 遍历K中的类型
js
interface IEx1 {
name: string,
age: number,
op: string
}
type TEx2 = Pick<IEx1, 'name' | 'age'> // { name: string; age: number; }
注意: 如果想生成的类型包含自定义属性,则需要在 原类型 中添加 [key: string]: any
typescript
interface IEx1 {
name: string,
age: number,
op: string,
[key: string]: any
}
type TEx2 = Pick<IEx1, 'name' | 'age' | 'other'> // { name: string; age: number; other: any}
Partial<Type>
将Type中的所有属性设置为可选
js
type Partial<T> = {
[P in keyof T]?: T[P]
}
// 获取T下面所有属性,然后遍历设置为?
js
interface IPart1 {
name: string,
age: number,
sex: string
}
type IPart2 = Partial<IPart1>
等同于:
type IPart2 = {
name?: string | undefined;
age?: number | undefined;
sex?: string | undefined;
}
Required<Type>
将Type中的所有属性设置为必须
js
type Required<T> = {
[P in keyof T]-?: T[p]
}
// '-?:' 字符语法的作用,标记映射类型的属性为必需。它只能在映射类型中使用,在其他类型中使用会报错
js
interface IRequired1 {
name: string,
age?: number,
job?: string
}
type Irequired2 = Required<IRequired1>
等同于:
type Irequired2 = {
name: string;
age: number;
job: string;
}
Readonly<Type>
将 Type 中的所有属性设为只读
bash
type Readonly<T> = {
readonly [P in keyof T]: T[P]
}
// readonly设置为只读
js
interface IReadonly1 {
name: string,
age: number
}
type IReadonly2 = Readonly<IReadonly1>
等同于
type IReadonly2 = {
readonly name: string;
readonly age: number;
}
Record<Keys, Type>
将 Keys 中的所有属性值都转换为 Type 类型,并返回新的对象类型
css
type Record<T, K> = {
[P in keyof T]: K
}
js
type TRecord1 = 'options1' | 'options2';
type KRecord = {
name: string,
age: string
}
type TRecord2 = Record<TRecord1, KRecord>;
等同于:
type TRecord2 = {
options1: KRecord;
options2: KRecord;
}
Exclude<UnionType, ExcludedMembers>
从UnionType中剔除可以赋值给ExcludedMembers的类型
js
type Exclude<T, U> = T extends U ? never : T
// T中有,U没有, 返回
// 就相当于找补集
如果T是联合类型,循环执行
(T1 extends U ? never : T1) | ( T2 extends U ? never : T2) | ...
js
type TExclude1 = Exclude<"a" | "b" | "c" | "d" , "a" | "c">
// T中有a,b,c,d。U中有a,c => b、d
等同于:
type TExclude1 = "b" | "d"
Extract<Type, Union>
提取Type中可以赋值给Union的类型
js
type Extract<T, U> = T extends U ? T : never
就相当于找交集
js
type TExtract1 = Extract<'a' | 'b' | 'c', 'a' | 'c'>
等同于:
type TExtract1 = "a" | "c"
NonNullable<Type>
去除 null 和 undefined 后的新类型
js
type NonNullable<T> = T extends null | undefined ? never : T
js
type TNo1 = null | number | boolean | undefined;
type TNo2 = NonNullable<TNo1>
等同于:
type TNo2 = number | boolean
Omit<Type, Keys>
获取 Type 中不包含 Keys 属性的 新类型
r
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
// keyof T 获取T中的所有类型
// Exclude<keyof T, K> Exclude T 中可以赋值的类型
// Pick 从T中选取可赋值的类型
js
interface IOm1 {
name:string,
age?: number,
sex: string,
}
type TOmit = Omit<IOm1, 'name' | 'sex' | 'op'>
等同于
type TOmit = {
age?: number | undefined;
}
ReturnType<Type>
提取函数的返回值类型
r
type ReturnType<T> = T extends (...args: any[]) => infer P ? P : any;
js
type Func = () => number;
type Test = ReturnType<Func>; // Test = number
2.2 Vue3.0 中的内置Ts类型
ComponentInternalInstance
用于声明getCurrentInstance
的类型
例如:
这里我们需要类型改成ComponentInternalInstance
js
import { getCurrentInstance, ComponentInternalInstance } from 'vue';
let { appContext } = getCurrentInstance() as ComponentInternalInstance;
Ref
声明一个Ref类型的响应式数据
js
import { ref, Ref } from 'vue';
export type componentListHooksType = {
listCount: Ref<number>
}
PropType
为props声明类型
js
import type { PropType } from 'vue'
export default defineComponent({
store: {
required: true,
type: Object as PropType<TableHeaderProps<DefaultRow>['store']>,
},
})
三. TS中的类型断言
个人觉得在Ts中类型断言是很重要的。有时候你会遇到这样的情况,你会比 TypeScript 更了解某个值的详细信息。通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编译器,"please 相信俺!"
。类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。它没有运行时的影响,只是在编译阶段起作用
。
类型断言有两种方式:
<Type>
江湖人称尖括号写法
js
let name: any = 'name';
let nameLen: number = (<string>name).length
as
js
type Td = {
name: string,
age: number,
sex: string
}
const Tarr = [] as Td[]
类型转换
Ts中的类型有高等级和低等级之分, 拿基本类型来说:
string | number | boolean 这些是平等的,也就是说不能把一个string类型直接断言到number类型。需要进行低等级类型的转换。比如: 先转为unknown 或者 any
举个例子:
先把str降级到any或者unknown,然后进行断言处理。
OK,这期的Ts大概就讲那么多。之后还会在补充。