Typescript 接口定义

207 阅读3分钟

Typescript 如何更优雅的定义接口以及类型

前言

这是我个人总结的一点 Typescript 定义接口的的方式,以及如何模拟提供的内置类型,因为用多了你会发现内置类型手动还原之后反而更好的进行加工。所以才有了这篇文章,新人第二次发文,如有什么不对的地方请大佬指正。

typeof 类型提取


提取参数的基本信息,原始类型获取类型,已用类型获取所有属性类型

const obj = { a: '1', b: true }
const str = ''

type Obj = typeof obj
type Str = typeof str

const a: Obj = { a: '', b: true }
const b: Str = ''

keyof 索引类型查询操作符


获取已知的公共属性名的联合

interface Person {
  name: string
  age: number
}

let person: Person = {
  name: 'Jarid',
  age: 35
}

let personProps: keyof Person = 'name' | 'age'

in 关键字 组合


判断是否存在于某个引用类型中

interface OrdinaryType {
  a: number
  b: number
  c: number
}

interface ComplexType {
  testA: string
  testB: string
}

function useIt(arg: OrdinaryType | ComplexType, target: string): boolean{
  return target in arg
}

console.log(useIt({a: 1, b: 1, c: 1}, 'a'))

用于缩小联合类型的范围

class caseA {
  a() {}
  useA() {
    return 'A'
  }
}

class caseB {
  b() {}
  useB() {
    return 'B'
  }
}

function useIt(arg: caseA | caseB, target: string): void {
  target in arg ? (arg as caseA).useA() : (arg as caseB).useB()
}

复制已有定义类型,二次加工,

interface Obj {
  a: string
  b: string
  c: string
}

type Foo = { [T in keyof Obj]: Obj[T] }

// 检出 Obj 所有的属性组成一个新的类型 

type Foo = { [T in keyof Obj]?: Obj[T] } // 等同于 Partial<T>
let foo: Foo = { a: '', b: '', c:'' }

// 将所有属性变成可选

type Foo = { [T in keyof Obj]-?: Obj[T] } // 等同于 Required<T>
let foo: Foo = { a: '', b: '', c:'' }

// 去除带有可选修饰符的属性,Obj 所有属性变更为必传

type Foo = { readonly [T in keyof Obj]: Obj[T] } 等同于 Readonly<T>
let foo: Foo = { a: '', b: '', c:'' }

// 增加可选修饰符的属性,Obj 所有属性变更为可选传

type Foo = { -readonly [T in keyof Obj]: Obj[T] }
let foo: Foo = { a: '', b: '', c:'' }

// 去除带有可读修饰符的属性,Obj 的所有属性变更为可修改

type Foo<T, K extends keyof T> = { [P in K]: T[P] } // 等同于 Pick<T, P>
let foo: Foo<Obj, 'a' | 'b'> = { a: '', b: '' }

// 从泛型 T 中检出指定的属性组成一个新的对象类型

type Foo<K extends keyof any, T> = { [P in K]: T } // 等同于 Record<K, T>
let foo: Foo<'c' | 'd', Obj> = { c: { a: '', b: '' }, d: { a: '', b: '' } } 

// 从泛型K检索出所有属性当作键名,创建一个新的类型用泛型 T 作为 键值

type Foo<T, U> = T extends U ? never : T // 等同于 Exclude<T, U>
type T0 = Foo<'a' | 'b' | 'c' | 'd', 'a' | 'b' | 'c'> // 'd'

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

type Foo<T, U> = T extends U ? T :  never // 等同于 Extract<T, U>
type T0 = Foo<'a' | 'b' | 'c' | 'd', 'a' | 'b' | 'c'> // 'a' | 'b' | 'd'

// 提取 T 中 U 存在的属性,然后赋值给U

type Foo<T> = T extends null | undefined ? never : T
type T0 = Foo<string | number | null> // string

// 从泛型 T 过滤 null 和 undefined 类型

type Foo<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any

// 获取返回类型

type Foo<T extends (...args: any) => any> = T extends (...args: infer R) => any
  ? R
  : never

// 获取方法参数类型

type Foo<T extends new (...args: any) => any> = T extends new (
  ...args: any
) => infer R
  ? R
  : never

// 获取构造函数参数类型

type Foo<T extends Promise<any>> = T extends Promise<infer R> ? R : never

// 获取 promise 参数类型

type DeepFoo<T> = {
  [P in keyof T]: T[P] extends object ? DeepFoo<T[P]> : T[P]
}

// 递归类型