blog
blog copied to clipboard
TypeScript的一些小用法 - 预定义的有条件类型
TypeScript的一些小用法 - 预定义的有条件类型
预先定义的条件类型(Predefined conditional types)
TS提供了几种内置的预定义的条件类型:
-
Exclude<T, U>-- 从T中剔除可以复制给U的类型。 -
Extract<T, U>-- 提取T中可以赋值给U的类型。 -
NonNullable<T>-- 从T中剔除null和undefined。 -
ReturnType<T>-- 获取函数返回值类型。 -
InstanceType<T>-- 获取构造函数类型的实例类型。
下面分别来举例:
1. Exclude
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
const str0: T00 = "d";
在这个例子中,因为用到了 Exclude 这个条件类型,会尝试寻找在 T 类型中有,但在 U 类型中没有的成员,最后将获取到的Union类型"b"|"d"赋给T100。
2. Extract
type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
const str01: T01 = "a"
Extract首先是提取出的意思,应用 Extract 条件类型,会尝试寻找T类型成员和U类型成员的交集,在该示例中,提取的是 "a"|"c"。
3. NonNullable
type T04 = NonNullable<string | number | undefined>; // string | number
const str04: T04 = 123
通过运行 NonNullable, 清除了 undefined 类型成员。
4. ReturnType
type T10 = ReturnType<() => string>; // string
type T11 = ReturnType<(s: string) => void>; // void
通过 ReturnType, 返回了泛型参数T的返回值类型。
5. InstanceType
class C {
x = 0;
y = 0;
}
type T20 = InstanceType<typeof C>; // C
Omit
目前的ts版本(3.2及以前)并没有内置Omit,那么Omit是什么呢?开始我对这个Omit也很好奇,在很多开源的实现里都能看到它的身影。Omit本身有省略和删除的意思,那在ts里这个Omit也很有可能有着相似的操作。查了一些资料之后,学习到,Omit确实是用来删除指定成员。ts虽然没有原生内置Omit,但却可以通过其他内置类型进行实现,比如:
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
搭配Pick这个映射类型,就可以实现 Omit 的效果,我们一点点来拆分这个类型实现。
首先看等号的右侧,Pick是一个ts内置的映射类型,Pick的实现为:
type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}
首先这个 "K extends keyof T" 说明这个类型值必须为T类型属性的子集,也就是说假如有一个 interface 定义如下:
interface Student {
name: string;
age: number;
}
在传入这个Student到Pick中时
type PickStudent1 = Pick<Student, "name">; // 正确
type PickStudent2 = Pick<Student, "score">; // 错误
在上面的Omit实现中,我们用到了 Exclude 这个条件类型,根据上文的说明,Exclude的效果就是寻找在keyof T中有,但在K类型中没有的成员,这样就将剩余的类型过滤了出来,再去应用Pick,就获得了我们的Omit实现。
完整例子:
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
interface Student {
name: string;
age: number;
}
type PickStudent1 = Pick<Student, "name">;