# ts高级特性

# keyof

  1. keyof运算符采用对象类型,并生成其键的字符串或数字文本联合
  2. 如果类型具有字符串或数字索引签名,则keyof将返回这些类型
interface IPeople {
name:string,
age?: number,
sex: string,
}

type T = keyof IPeople

// 等同于
//type T = "name" | "age" | "sex"
type Mapish = { [k: string]: boolean };
type M = keyof Mapish;
//type M = string | number

在本例中,M是字符串|数字-这是因为JavaScript对象键始终被强制为字符串,因此obj[0]始终与obj['0']相同。

TIP

type TAny = keyof any

// 等同于

// type TAny = string | number | symbol //不包括 boolean object等

# Record

将 K 中的所有属性值都转换为 T 类型,并返回新的对象类型

  • keyof any: 等同于 string | number | symbol ,也就是说 K 只能是这三种类型
  • P in K: 指循环 K 类型
 type Record<K extends keyof any, T> = {
    [P in K]: T;
  };
  type TKeys = 'A' | 'B' | 'C'

  interface IPeople {
    name:string,
    age?: number,
    sex: string
  }

  type TRecord = Record<TKeys, IPeople>
  
  // 等同于
//   type TRecord = {
//     B: IPeople;
//     C: IPeople;
//     A: IPeople;
//   }

# Pick

从 T 类型中选取部分 K 类型,并返回新的类型,这里 T 常用于对象类型

  • keyof T 获取 T 中所有的 key 属性
  • K extends keyof T K 必须继承于 keyof T ,如果 K 中的属性有不属于 keyof T 的则会报错
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};
  interface IPeople {
    name:string,
    age?: number,
    sex: string,
  }
  
  type TPick = Pick<IPeople, 'name' | 'age'>
  
// 等同于
//   type TPick = {
//     name: string;
//     age?: number | undefined;
//   }

注意: 如果想生成的 TPick 包含自定义属性,则需要在 IPeople 中添加 [key: string]: any

  interface IPeople {
    name:string,
    age?: number,
    sex: string,
    [key: string]: any
  }

  type TPick = Pick<IPeople, 'name' | 'age' | 'color'>

//   等同于
//   type TPick = {
//     name: string;
//     age?: number | undefined;
//     color: any;
//   }

# Partial

将T中的所有属性设置为可选

type Partial<T> = {
    [P in keyof T]?: T[P];
};
  interface IPeople {
    name:string,
    age?: number,
    sex: string,
  }
  type TPartial = Partial<IPeople>
  
  // 等同于
//   type TPartial = {
//     name?: string | undefined;
//     age?: number | undefined;
//     sex?: string | undefined;
//   }

# Required

使 T 中的所有属性都变成必需的

  • -?: 通过 -? 把所有属性变成 必需的
 type Required<T> = {
    [P in keyof T]-?: T[P];
  }
  interface IPeople {
    name:string,
    age?: number,
    sex: string,
  }
  type TRequired = Required<IPeople>

  // 等同于
//   type TRequired = {
//     name: string;
//     age: number;
//     sex: string;
//   }

# Readonly

将 T 中的所有属性设为只读

type Readonly<T> = {
    readonly [P in keyof T]: T[P];
  }
  interface IPeople {
    name:string,
    age?: number,
    sex: string,
  }
  type TReadonly = Readonly<IPeople>

//   // 等同于
//   type TReadonly = {
//      readonly name: string;
//      readonly age?: number | undefined;
//      readonly sex: string;
//   }

# Exclude

从T中剔除可以赋值给U的类型

  • 当 T 是联合类型时,则会循环 T 类型即: (T1 extends U ? never : T1) | (T2 extends U ? never : T2) | …
type Exclude<T, U> = T extends U ? never : T
type TExclude1 = Exclude<"a" | "b", "a" | "c">
// 等同于
type TExclude1 = "b"

type TExclude2 = Exclude<number | string | boolean, string>
// 等同于
type TExclude2 = number | boolean

# Extract

提取T中可以赋值给U的类型

  • 当 T 是联合类型时,则会循环 T 类型即: (T1 extends U ? T1 : never ) | (T2 extends U ? T2 : never ) | …
 type Extract<T, U> = T extends U ? T : never
type TExtract1 = Extract<"a" | "b", "a" | "c">
// 等同于
type TExtract1 = "a"

type TExtract2 = Extract<number | string | boolean, string>
// 等同于
type TExtract2 = string

type TExtract3 = Extract<number | string | boolean, object>
// 等同于
type TExtract3 = never

# Omit

获取 T 中不包含 K 属性的 新类型

  1. keyof any 等同于 string | number | symbol ,也就是说 K 只能是这三种类型
  2. keyof T 获取 T 的所有属性
  3. Exclude 从T中剔除可以赋值给U的类型
  4. Pick 从 T 类型中选取部分 K 类型,并返回新的类型,这里 T 常用于对象类型
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>

说明:先通过 Exclued 获取 T 中不包含 K 属性的新类型, 再通过 Pick 获取 T 中包含 K 属性的新类型

  interface IPeople {
    name:string,
    age?: number,
    sex: string,
  }

  type TOmit = Omit<IPeople, 'name' | 'sex' | 'color'>

  // 等同于
  type TOmit = {
    age?: number | undefined;
  }

# NonNullable

去除 null 和 undefined 后的新类型

  • 当 T 是联合类型时,则会循环 T 类型即: (T1 extends U ? never : T1) | (T2 extends U ? never : T2) | …
type NonNullable<T> = T extends null | undefined ? never : T
  type TType= number | null | undefined
  type TNonNullable = NonNullable<TType>
  // 等同于
  // type TNonNullable = number

# typeof在ts中的应用

  1. 自动生成对象的类型,如果对象上有类型则使用定义的类型
  const people = {
    name: "liuyz",
    age: 20,
    info: {
      sex: "man",
      hobby: "sleep",
    }
   }
  
  type IPeople = typeof people
  // 等同于
  // type IPeople = {
  //   name: string
  //   age: number
  //   info: {
  //     sex: string
  //     hobby: string
  //   }
  // }
  
  type IPeople1 = keyof typeof people  // keyof 只会获取数据类型的第一级属性key
  // 等同于
  // type IPeople1 = "name" | "age" | "info"
  1. 函数使用
  const add = (a: number, b: number): number => {
    return a + b
  }
  
  type TFunType = typeof add // 获取函数类型
  // 等同于
  // type TFunType = (a: number, b: number) => number
  type TReturnType = ReturnType<TFunType> // 获取函数返回值类型
  // 等同于
  // type TReturnType = number
  type TParamsType = Parameters<TFunType> // 获取函数参数类型,转变为元组类型
  // 等同于
  // type TParamsType = [a: number, b: number] // 元组类型

  1. 数组使用
  const arr = ['liu', 'y', 'z']
  type IArr = typeof arr
  // 等同于
  // type IArr = string[]
    
  const arr = ['liu', 'y', 1]
  type IArr = typeof arr
  // 等同于
  // type IArr = (string | number)[] // 字符串或数字 数组
    
  type IKey = keyof typeof arr
  // 等同于
  // type IKey = keyof string[]

注意:数组上使用 keyof typeof arr 是没有意义的

  1. 枚举使用
enum EDirection {
UP = "UP",
DOWN = "DOWN",
}

type TDirection = typeof EDirection

const direction: TDirection = {
UP: EDirection.UP,
DOWN: EDirection.DOWN,
}

console.log(direction) // { UP: 'UP', DOWN: 'DOWN' }

type TNewDirection = keyof typeof direction
// 等同于
// type TNewDirection = "UP" | "DOWN"

let newDirection: TNewDirection = "DOWN" // 这里只能取值 UP 或 DOWN

5.基本类型使用: 并没有什么意义

  const bool = true
  type TBool = typeof bool
  // 等同于
  // type TBool = true
  let newBool: TBool = true // 此时 newBool 只能赋值 true,否则报错
    
  const str = "test"
  type IStr = typeof str
  // 等同于
  // type IStr = "test"
  let newStr: IStr = "test" // 此时 newStr 只能赋值 test,否则报错
    
  const num = 10
  type INum = typeof num
  // 等同于
  // type INum = 10
  let newNum: INum = 10 // 此时 newNum 只能赋值 10,否则报错

# TS extends类型约束

这里的 extends 关键词不同于在 class 后使用 extends 的继承作用,泛型内使用的主要作用是对泛型加以约束

最后更新: 12/3/2022, 9:27:50 AM