一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情。
根据已知的信息, 计算出新的类型。
三个关键字
typeof
这里所指的 typeo
f 是指书写的位置在类型约束的位置上。
有这样一种场景, b
的 类型要和 a
的类型一致, 就可以使用 typeof
const a = '123'
const b: typeof a = '123'
这里的 a
是 string
所以 b
也是 string
当 typeof
作用于类时, 得到的是构造函数
class User {
name:string = 'John';
}
function printClass(target: typeof User){
}
target: typeof User
约束改参数必须是 user
构造函数本身
keyof
keyof
作用于 类、接口、类型别名, 用于获取该类型中的所有成员名组成的联合类型。
听起来有点绕, 举个栗子马上明白
有一个约束用户类的接口
interface User {
name:string
age:number
sex:string
}
假如现在要写一个打印用户对象的函数 printUser
, 需要传递两个参数: 用户对象, 需要打印的属性名。
function printUser(target: User, prop: string) {
console.log(target[prop]) //target[prop] 已经报错了
}
函数的实现看起来没有问题, 怎么会报错呢?
原因在于参数 prop
的类型为string
但是用户对象不一定有prop
属性, 所以prop
只能传递为 name, age, sex
, 因为用户对象目前只有这上三个属性,所以prop
可以写为 prop: 'name' |'age' | 'sex'
, 很明显这样写过于繁琐所以这里应该使用keyof
function printUser(target: User, prop: keyof User) {
console.log(target[prop])
}
in
in
经常与 keyof
联用
有这样一种场景有一个 User
接口
interface User {
name: string
sex: string
age: number
}
现在有一个 类型别名需要和 User
的成员一致并且是自读的, 那么可以通过 in + keyof
实现这样一种效果
type ReadonlyUser = {
readonly [key in keyof User]: User[key]
}
这就动态的将 User
接口的所有成员和类型都设置为只读, 并且还可以配合 泛型 变成一个通用的
type ReadonlyUser<T> = {
readonly [key in keyof T]: T[key]
}
TS 中已经预设好的类型推演
-
Partial<T>
: 将类型 T 中的成员变为可选 -
Required<T>
: 将类型 T 中的成员变为必填 -
Readonly<T>
: 将类型 T 中的成员变为只读 -
Exclude<T, K>
: 从 T 中剔除可以赋值给 K 的成员
type T = 'a' | 'b' | 'c' | 'd'
type K = 'a' | 'e' | 'c' | 'w'
const test:Exclude<T, K> = "b" //test 只能赋值为"b" | "d"
-
Extract<T, K>
: 提取 T 中可以赋值给 K 的成员 -
NonNullable<T>
: 从 T 中剔除 null 和 undefined
type T = 'a' | null | 'c' | undefined
const test:NonNullable<T> = 'a' //test 只能赋值为 "a" | "c"
ReturnType<F>
: 获取 F 类型的返回值类型
type F = (a: number, b: number) => number
const test: ReturnType<F> = 123 //test 的类型为 number
InstanceType<C>
: 获取 C 构造函数类型的实例类型
class C {
}
const test:InstanceType<typeof C> = new C()
总结
类型演算是通过已有的类型可以做出一些自定义的类型