Allen Yu Allen Yu
Home
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《TypeScript入门教程》
GitHub (opens new window)
Home
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《TypeScript入门教程》
GitHub (opens new window)
  • 开始

  • 基础

  • 进阶

    • 类型别名
    • 字符串字面量类型
    • 元组
    • 枚举
    • 类
    • 类与接口
    • 泛型
    • 声明合并
    • 工具类型
      • Partial
        • 使用
        • 实现
      • Required
        • 使用
        • 实现
      • Readonly
        • 使用
        • 实现
      • Record<K, T>
        • 使用
        • 实现
      • Pick<T, K>
        • 使用
        • 实现
      • Exclude<T, U>
        • 使用
        • 实现
      • Omit<T, K>
        • 使用
        • 实现
      • Extract<T, U>
        • 使用
        • 实现
      • NonNullable
        • 使用
        • 实现
      • Parameters
        • 使用
        • 实现
      • ConstructorParameters
        • 使用
        • 实现
      • ReturnType
        • 使用
        • 实现
      • TS Compiler 内部类型
        • Uppercase
        • Lowercase
        • Capitalize
        • Uncapitalize
      • 参考
    • 编译配置
  • 实战

  • TypeScript
  • 进阶
2022-04-01
目录

工具类型

TypeScript 提供了一些工具类型,方便进行类型上的转换。这些工具类型是全局可见的。

# Partial

构造一个新类型,使类型 T上的所有属性都变成可选的。

# 使用

interface Person {
  name: string
  age: number
}

type PersonOptional = Partial<Person>

// 相当于
type PersonOptional = {
  name?: string
  age?: number
}

# 实现

type Partial<T> = {
  [K in keyof T]?: T[K]
}

# Required

设置类型的所有属性为必须项。和 Partial 是相反的。

# 使用

interface Person {
  name?: string
  age?: number
}

const Jack: Person = { name: 'Jack' }
const Lucy: Required<Person> = { name: 'Lucy' }

// Property 'age' is missing in type '{ name: string; }' but required in type 'Required<Person>'.(2741)

# 实现

type Required<T> = {
  [K in keyof T]-?: T[K]
}

注意 -? 表示非可选,这里如果不加 -? 在遇到 T 的属性为可选时,就无法变成必选属性,这个就是指同态拷贝。

举个例子 🌰

interface T {
  name: string
  age?: number
}

// 实现一个不使用 `-?` 的 Required
type Required<T> = {
  [K in keyof T]: T[K]
}

// Foo = { name: string, age?: number | undefined }
type Foo = Required<T>

// 添加 `-?`
type Required<T> = {
  [K in keyof T]-?: T[K]
}

// Foo = { name: string, age: number }
type Foo = Required<T>

# Readonly

设置类型的所有属性为 readonly。也就是不能再被赋值。

# 使用

interface Person {
  name: string
  age: number
}
const Lucy: Readonly<Person> = { name: 'Lucy', age: 18 }
Lucy.name = 'Jack'
// Cannot assign to 'name' because it is a read-only property.

# 实现

type Readonly<T> = {
  readonly [K in keyof T]: T[K]
}

# Record<K, T>

构造一个对象类型, 它的 Keys 是 K,它的 value 是 T。

# 使用

type Point = {
  lat: number
  lng: number
}
type Line = Record<'start' | 'end', Point>

// 相当于
type Line = {
  start: { lat: number; lng: number }
  end: { lat: number; lng: number }
}

# 实现

type Record<K extends keyof any, T> = {
  [P in K]: T
}

# Pick<T, K>

接口类型工具,从 T 类型中,选取 K 选项的属性,并组成新的类型。

# 使用

type House = {
  lat: number
  lng: number
  address: string
  color: string
}

type Point = Pick<House, 'lat' | 'lng'>

// 相当于
type Point = {
  lat: number
  lng: number
}

# 实现

type Pick<T, K extends keyof T> = {
  [P in K]: T[P]
}

# Exclude<T, U>

联合类型工具,排除联合类型 T 中与 U 相等的类型,返回一个联合类型。

# 使用

interface Person {
  name: string
  age: number
}

type P = Exclude(keyof Person, 'age')

# 实现

type MyExclude<T, U> = T extends U ? never : T

# Omit<T, K>

从类型 T 中移除 K 中所有的属性。

# 使用

type House = {
  lat: number
  lng: number
  address: string
  color: string
}

// 移除 House 类型中的 color 和 address
type Point = Pick<House, 'color' | 'address'>

// 相当于
type Point = {
  lat: number
  lng: number
}

# 实现

type MyExclude<T, U> = T extends U ? never : T
type MyOmit<T, K extends keyof T> = {
  [P in MyExclude<T, U>]: T[P]
}

# Extract<T, U>

联合类型工具,联合类型 T 和 U 的交集。

# 使用

type T = Extract<'name' | 'age' | 'sex', 'age' | 'height'>

// 相当于
type T = 'age'

# 实现

type MyExtract<T, U> = T extend U ? T : never

# NonNullable

排除联合类型中为 null 和 undefined 的类型

# 使用

type T = NonNullable<string | number | undefined | null>

// 等于
type T = string | number

# 实现

type MyNonNullable<T> = Exclude<T, null | undefined>

# Parameters

获取函数的参数类型,将每个参数类型放在一个元组中

# 使用

declare function f1(arg: { a: number; b: string })

type T0 = Parameters<() => string>
// T0 = []

type T1 = Parameters<(s: string) => void>
// T1 = [s: string]

type T2 = Parameters<<T>(arg: T) => T>
// T2 = [arg: unknown]

type T3 = Parameters<typeof f1>
// T3 = [arg: { a: number, b: string }]

# 实现

type MyParameters<T extends (...arg: any) => any> = T extends (
  ...args: infer P
) => any
  ? P
  : never

# ConstructorParameters

获取类的构造函数的参数类型,存在一个元组中。

# 使用

class People {
  constructor(public name: string, age?: number) {}
}

type Options = ConstructorParameters<typeof People>

// type Options = [name: string, age?: number | undefined]

# 实现

type MyConstructorParameters<T extends abstract new (...args: any) => any> =
  T extends abstract new (...args: infer P) => any ? P : never

# ReturnType

获取函数的返回值类型

# 使用

const getPeopleInfo: (name: string) => {
  name: string
  age: number
  weight: string
  sex: string
} = (name: string) => {
  return {
    name,
    age: 18,
    weight: '79kg',
    sex: 'male',
  }
}

type T = ReturnType<typeof getPeopleInfo>
// T = { name: string; age: number; weight: string; sex: string; }

# 实现

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

# TS Compiler 内部类型

# Uppercase

构造一个将字符串转大写的类型

type T = Uppercase<'abcde'>
// T = 'ABCDE'

# Lowercase

构造一个将字符串转小写的类型

type T = Lowercase<'ABCDe'>
// T = 'abcde'

# Capitalize

构造一个将字符串首字母转大写的类型

type T = Capitalize<'allen'>
// T = 'Allen'

# Uncapitalize

构造一个将字符串首字母转小写的类型

type T = Uncapitalize<'ALLEN'>
// T = aLLEN

# 参考

  • Utility Types (opens new window)
Last Updated: 4/8/2022, 2:53:25 PM
声明合并
编译配置

← 声明合并 编译配置→

最近更新
01
4 月第 2 周总结
04-17
02
Google 搜索小技巧
03-28
03
出租房屋小记
03-26
更多文章>
Theme by Vdoing | Copyright © 2018-2022 Allen Yu
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式