参考
Reference / Utility Types (opens new window)
Reference / Modules (opens new window)
Declaration Files / Declaration Reference (opens new window)
# 一、ts 内置工具
提示
# 1、Partial<Type>
构造一个类型,并将 Type 的所有属性都设置为可选。
interface Foo {
a: number
b?: number
}
type PartialFoo = Partial<Foo> // { a?: number, b?: number}
实现原理
type Partial<T> = {
[P in keyof T]?: T[p]
}
# 2、Required<Type>
interface Foo {
a: number
b?: number
}
type RequiredFoo = Required<Foo> // { a: number, b: number}
实现原理
type Required<T> = {
[P in keyof T]-?: T[p]
}
# 3、Readonly<Type>
interface Foo {
a: number
b?: number
}
type ReadonlyFoo = Readonly<Foo> // { readonly a: number,readonly b?: number | undefined}
实现原理
type Readonly<T> = {
readonly [P in keyof T]: T[p]
}
# 4、Exclude<T, E>
从类型 T 中排除掉 T、E 两者间的交集部分
// 使用1
type Foo = 'a' | 'b' | 'c'
type Bar = Exclude<Foo, 'a'> // "b" | "c"
// 使用2
type Foo = Exclude<1 | 2, 1 | 3> // 2
实现原理
type Exclude<T, E> = T extends E ? never : T
# 5、Extract<T, U>
提取 T、U 两者间的交集部分 (和 Exclude 相反)
// 使用1
type Foo = 'a' | 'b' | 'c'
type Bar = Extract<Foo, 'a'> // "a"
// 使用2
type Foo = Extract<1 | 2, 1 | 3> // 1
实现原理
type Extract<T, U> = T extends U ? T : never
# 6、NonNullable<Type>
排除掉 null 和 undefined 类型
type T0 = NonNullable<string | number | undefined>
// type T0 = string | number
type T1 = NonNullable<string[] | null | undefined>
// type T1 = string[]
实现原理
type NonNullable<T, U> = T extends null | undefined ? never : T
# 7、ThisType<Type>
interface IState {
name: string
age: number
}
interface IStore {
state: IState
eating: () => void
running: () => void
}
// 方式2
const store: IStore & ThisType<IState> = {
state: {
name: 'lencamo',
age: 20
},
// eating: function (this: IState) { // 方式1
// console.log(this.name) // 这样就可以不使用 this.state.name 了
// },
running: function () {
console.log(this.age)
}
}
store.eating.call(store.state)
# 二、类型继承 extends
提前说明一下,下面部分的内容最好是已经看过了面向对象部分的:泛型约束、类型映射等知识
# extends
SomeType extends OtherType ? TrueType : FalseType
type IDType = number | string
type ResType = number extends IDType ? true : false
关于函数重载的思考
function sum(num1, num2) {
return num1 + num2
}
- 函数重载
function sum(num1: number, num2: nubmer): number
function sum(num1: string, num2: string): string
- 使用泛型
// 联合类型中的一个
function sum<T extends number | string>(num1: T, num2: T): T extends number ? number : string
# 1、Record<Keys, Type>
用于仅对象和 keys 映射构造一个对象类型
interface CatInfo {
age: number
breed: string
}
type CatName = 'miffy' | 'boris' | 'mordred'
const cats: Record<CatName, CatInfo> = {
miffy: { age: 10, breed: 'Persian' },
boris: { age: 5, breed: 'Maine Coon' },
mordred: { age: 16, breed: 'British Shorthair' }
}
对 Record 的封装
Record<Keys, Type>
// 联合类型中的一个
type MyRecord<Keys extends keyof any, T> = {
[P in Keys]: T
}
- 使用
interface CatInfo {
age: number
breed: string
}
type CatName = 'miffy' | 'boris' | 'mordred'
const cats: Record<CatName, CatInfo> = {
miffy: { age: 10, breed: 'Persian' },
boris: { age: 5, breed: 'Maine Coon' },
mordred: { age: 16, breed: 'British Shorthair' }
}
cats.boris
# 2、Pick<Type, Keys>
在对象类型中选择一部分 key 作为一个新的对象类型
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = Pick<Todo, 'title' | 'completed'>
const todo: TodoPreview = {
title: 'Clean room',
completed: false
}
todo
对 Pick 的封装
Pick<Type, Keys>
// 联合类型中的一个
type MyPick<T, Keys extends keyof T> = {
[P in Keys]: T[P]
}
- 使用
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = Pick<Todo, 'title' | 'completed'>
const todo: TodoPreview = {
title: 'Clean room',
completed: false
}
todo
# 3、Omit<Type, Keys>
和 Pick 的作用相反
// 略
对 Omit 的封装
Omit<Type, Keys>
Omit 和 Pick 的作用是相反的
// 联合类型中的一个
type MyOmit<T, Keys extends keyof T> = {
// 先拷贝,后筛选(类似于Exclude<T, U>的实现)
[(P in keyof T) as P extends Keys ? never : P ]: T[P]
}
# 三、类型推断 infer
# 1、ReturnType<Type>
ReturnType 是用于获取函数返回值类型
- 简单场景
function foo() {
return 'lencmao'
}
// 常规
type FooReturnType = ReturnType<typeof foo>
// 使用ts内置工具
type FooReturnType = ReturnType<foo>
- 复杂场景
type T1 = ReturnType<(s: string) => void>
// type T1 = void
type T2 = ReturnType<() => string>
// type T2 = string
type T3 = ReturnType<<T extends U, U extends number[]>() => T>
// type T3 = number[]
对 ReturnType 的封装
ReturnType<Type>
type CalcFnType = (num1: nubmer, num2: nubmer) => nubmer
// 推断返回值类型
type MyReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R
? R
: never
type CalcReturnType = MyReturnType<CalcFnType>
# 2、Parameters<Type>
Parameters 是用于获取函数参数类型
type T0 = Parameters<() => string>
// type T0 = []
type T1 = Parameters<(s: string) => void>
// type T1 = [s: string]
type T2 = Parameters<<T>(arg: T) => T>
// type T2 = [arg: unknown]
对 Parameters 的封装
Parameters<Type>
type CalcFnType = (num1: nubmer, num2: nubmer) => nubmer
// 推断参数类型
type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer P) => any
? P
: never
type CalcReturnType = MyParameters<CalcFnType>
# 3、InstanceType<Type>
InstanceType 用于获取构造函数创建的实例对象的类型
- 获取实例对象类型
class C {
x = 0
y = 0
}
type T0 = InstanceType<typeof C>
// type T0 = C
<template>
<Son ref="sonRef" />
</template>
<script setup lang="ts">
import Son from './Son.vue'
const sonRef = ref<InstanceType<typeof Son>>()
//……
</script>
- 使用实例对象类型
function factory<T extends new (...args: any[]) => any>(ctor: T): InstanceType<T> {
return new ctor()
}
const T1 = factory(C)
对 InstanceType 的封装
InstanceType<Type>
class Person {}
type MyInstanceType<T extends new (...args: any[]) => any> = T extends new (
...args: any[]
) => infer R
? R
: never
type p1 = MyInstanceType<typeof Person>
# 四、类型分发
当我们在泛型中使用条件类型的时候,如果传入的是一个联合类型,就会变成分发的
- 普通使用(不分发)
type toArray<T> = T[]
type NumArray = toArray<number>
type NumArray = toArray<string | number>
// (string | number)[]
- 特殊使用(分发)
// 泛型中使用条件类型
type toArray<T> = T extends any ? T[] : never
type NumArray = toArray<number>
// 传入的是一个联合类型
type NumArray = toArray<string | number>
// string[] | number[]