TypeScript笔记
Utility Types
Omit<Type,Keys>
Constructs a type by picking all properties from Type
and then removing Keys
(string literal or union of string literals).
通过从 Type
中选取所有属性,然后移除 Keys
(字符串文字或字符串文字的并集)来构造类型。
interface Todo {
title: string
description: string
completed: boolean
createdAt: number
}
type TodoPreview = Omit<Todo, 'description'>
//expect:
//type TodoPreview = {
// title: string;
// completed: boolean;
// createdAt: number;
//}
实现 MyOmit
借助 Exclude 类型:
type MyOmit<T, U> = {
[P in Exclude<keyof T, U>]: T[P]
}
原始实现方式:
type MyOmit<T, U extends keyof T> = {
[P in keyof T as P extends U ? never : P]: T[P]
}
Exclude<UnionType, ExcludedMembers>
Constructs a type by excluding from UnionType
all union members that are assignable to ExcludedMembers
.
通过从 UnionType
中排除可分配给 ExcludedMembers
的所有联合成员来构造类型.
type T = Exclude<'a' | 'b' | 'c', 'a'> //Expect: type T = "b" | "c"
实现 Exclude
type MyExclude<T, K> = T extends K ? never : T
Extract<Type, Union>
Constructs a type by extracting from Type
all union members that are assignable to Union
.
通过从 Type 中提取可分配给 Union 的所有联合成员来构造类型。
type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>
//expect:
//type T0 = "a"
type T1 = Extract<string | number | (() => void), Function>
//expect
//type T1 = () => void
实现 Extract
type MyExtract<T, U> = T extends U ? T : never
Record<Keys, Type>
Constructs an object type whose property keys are Keys
and whose property values are Type
. This utility can be used to map the properties of a type to another type.
构造属性键为 Keys
、属性值为 Type
的对象类型。此实用工具可用于将类型的属性映射到另一个类型。
interface CatInfo {
age?: number
color?: string
}
type CatName = 'Tom' | 'Jerry'
const cats: Record<CatName, CatInfo> = {
Tom: { age: 2 },
Jerry: { age: 3 },
}
实现 Record
type MyRecord<K extends string | number | symbol, T> = {
[P in K]: T
}
Some Cases
从接口中拓展新类型
例如需要从 IProduct
这个商品接口中添加 quantity
属性,并且剔除 inventory
属性以生成一个 CartProduct
类型。
interface IProduct {
id: number
title: string
price: number
inventory: number
}
type CartProduct = {
quantity: number
} & Omit<IProduct, 'inventory'>
/** 预期:
type CartProduct = {
id: number
title: string
price: number
quantity: number
}
*/
从数组元素值中定义 Union Type
students 是一个包含每个学生信息的数组:
const students = [
{
name: 'tom',
age: 20,
},
{
name: 'jack',
age: 19,
},
]
如果想要提取出 students
中学生的姓名组成一个新的联合类型,可以这样做:
type studentName = 'tom' | 'jack'
但是这样每当 students
数组中的元素增加了,那么就需要手动更新 studentName
的定义,这明显不够优雅。
所以可以使用 const
类型断言配合索引访问的方式来优雅实现:
const students = [
{
name: 'tom',
age: 20,
},
{
name: 'jack',
age: 19,
},
] as const
type studentName = typeof students[number]['name']
// 预期:
// type studentName = 'tom' | 'jack'
但在实际开发中,我们通常会预先定义每个 student
的类型:
type Student = {
name: string
age: number
}
const students: Student[] = [
{
name: 'tom',
age: 20,
sex: 'male',
},
{
name: 'jack',
age: 19,
sex: 'female',
},
]
type studentName = typeof students[number]['name']
// 不符合预期:
// type studentName = string
但是你会发现先前的解决方案就失效了,这是因为 Student[]
是一个可变类型。
如果要解决这个问题,就需要使用泛型函数:
type Student<T> = {
name: T
age: number
}
function defineStudents<T extends string>(students: Student<T>[]) {
return students
}
const students = defineStudents([
{
name: 'tom',
age: 20,
sex: 'male',
},
{
name: 'jack',
age: 19,
sex: 'female',
},
])
type studentName = typeof students[number]['name']
// 符合预期:
// type studentName = 'tom' | 'jack'
不过有个问题:为什么
defineStudents
需要T extends string
才有效果?
这个案例学习了这一篇文章: https://fehey.com/typescript-const-generic-union-type/ 非常感谢!
这篇学习记录参考和学习了以下内容: