typescript 高级用法

运算符

  1. 非空断言运算符 !
    !放在变量名或函数名后,用来强调该变量名或函数名非null|undefined。
    这个符号特别适用于我们已经明确知道不会返回空值的场景。
function onClick(callback?: () => void) {
  callback!();		// 参数是可选入参,加了这个感叹号!之后,TS编译不报错
}
  1. 可选链运算符 ?.
    判断左侧的表达式是否是 null | undefined,如果是则会停止表达式运行,可以减少我们大量的&&运算。
a?.b
// 相当于
a === null || a === void 0 ? void 0 : a.b;
  1. 空值合并运算符 ??
    ??在左侧表达式结果为 null 或者 undefined 时,才会返回右侧表达式 .
let b = a ?? 10
// 相当于
let b = a !== null && a !== void 0 ? a : 10;

操作符

  1. keyof
    获取一个类型所有键值,返回一个联合类型
type Person = {
  name: string;
  age: number;
}
type PersonKey = keyof Person;  // PersonKey得到的类型为 'name' | 'age'

keyof 的一个典型用途是限制访问对象的 key 合法化,因为 any 做索引是不被接受的。

function getValue (p: Person, k: keyof Person) {
  return p[k];  // 如果k不如此定义,则无法以p[k]的代码格式通过编译
}
  1. typeof
    获取一个对象/实例的类型。
const me: Person = { name: 'gzx', age: 16 };
type P = typeof me;  // { name: string, age: number | undefined }
const you: typeof me = { name: 'mabaoguo', age: 69 }  // 可以通过编译

typeof 可以和 keyof 一起使用(因为 typeof 是返回一个类型)

type PersonKey = keyof typeof me;   // 'name' | 'age'
  1. 遍历属性 in
    in 只能用在类型的定义中,可以对枚举类型进行遍历。
// 这个类型可以将任何类型的键值转化成number类型
type TypeToNumber<T> = {
  [key in keyof T]: number
}

const obj: TypeToNumber<Person> = { name: 10, age: 10 }

泛型

泛型推断infer

type Foo<T> = T extends {t: infer Test} ? Test : string

{t: infer Test} 是一个类型对象,包含属性t,t的value类型通过infer进行推断后会赋值给Test类型。

举例:

type One = Foo<number>  // string,因为number不是一个包含t的对象类型
type Two = Foo<{t: boolean}>  // boolean,因为泛型参数匹配上了,使用了infer对应的type
type Three = Foo<{a: number, t: () => void}> // () => void,泛型定义是参数的子集,同样适配

type ParamType<T> = T extends (param: infer P) => any ? P : T;

infer P 表示待推断的函数参数。如果T能赋值给(param: infer P) => any,则结果为参数P类型,否则返回T。

举例:

interface User {
  name: string;
  age: number;
}

type Func = (user: User) => void
let type1 = ParamType<Func> // User
let type2 = ParamType<string> // string

提取函数类型的返回值类型:

type ReturnType<T> = T extends (...args: any[]) => infer P ? P : any;

ReturnType 只是将 infer P 从参数位置移动到返回值位置,因此此时 P 即是表示待推断的返回值类型。

举例:

type Func = () => User;
type Test = ReturnType<Func>;   // Test = User

泛型工具

  1. Partial
    将泛型中的全部属性变成可选
type Partial<T> = {
    [P in keyof T]?: T[P]
}

举例:

type Animal = {
  name: string,
  category: string,
  age: number,
  eat: () => number
}

type PartOfAnimal = Partial<Animal>
const ww: PartOfAnimal = { name: 'ww' }; // 属性全部可选后,可以只赋值部分属性了
  1. Record<K, T>
    将K中左右的属性值都转化成T类型
type Record<K extends keyof any, T> {
    [P in K]: T
}

keyof any对应的类型为number | string | symbol,也就是可以做对象键(专业说法叫索引 index)的类型集合

举例:

const obj: Record<string, string> = { 'name': 'zhangsan', 'tag': '打工人' }
  1. Pick<T, K>
    将类型T中的属性K提取出来,生成新的键值对。
type Pick<T, K extends keyof T> = {
    [P in K]: T[P]
}

举例:

type Animal = {
  name: string,
  category: string,
  age: number,
  eat: () => number
}

const bird: Pick<Animal, "name" | "age"> = { name: 'bird', age: 1 }
  1. Exclude<T, U>
    去除T类型中和U类型有交集的部分,返回剩余部分
type Exclude<T, U> = T extends U ? never : T

举例:

type T1 = Exclude<"a" | "b" | "c", "a" | "b">;   // "c"
  1. Omit<T, K>
    Construct a type with the properties of T except for those in type K.
type Omit <T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>

第一步先从 T 的 key 中去掉与 K 重叠的 key,接着使用 Pick 把 T 类型和剩余的 key 组合起来即可。

举例:

type Animal = {
  name: string,
  category: string,
  age: number,
  eat: () => number
}

const OmitAnimal:Omit<Animal, 'name'|'age'> = { category: 'lion', eat: () => { console.log('eat') } }
  1. ReturnType
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

// 可以简化为:

type ReturnType<T> = T extends (...args: any) => inter R ? R : any 

ReturnType 只是将 infer R 从参数位置移动到返回值位置,因此此时 R 即是表示待推断的返回值类型

  1. Required
    将类型 T 中所有的属性变为必选项
type Required<T> = {
    [P in keyof T]-?: T[P];
};

Typescript高级用法

posted @ 2022-06-30 19:43  webLion200  阅读(215)  评论(0编辑  收藏  举报