从0开始的 TypeScript之十四:内置工具类型

本文介绍了TypeScript中的一些内置工具类型,如Readonly、Partial、Pick等,它们用于简化代码并处理类型操作,如将属性设为只读、可选、提取部分属性等。同时,展示了如何使用这些工具进行数组扁平化的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在之前的《从0开始的TypeScriptの十三》中,已经对typescript的工具类型中的关键字infer、extends、keyof、typeof、in这些有所了解了,那么接下来为了使用更加方便,可以对typescript中内置的工具类型进行一些学习。

工具类型名称描述用法
Readonly<T>将 T 中所有属性都变为只读Readonly<{ a: number }> <===> { readonly a: number }
ReadonlyArray<T>返回一个 T 类型的只读数组ReadonlyArray<string> <===> readonly string[]
Partial<T>将 T 中所有的属性都变成可选类型Partial<{ a: number }> <===> { a?: number }
Required<T>将 T 中所有的属性都变成必选类型和上面的Partial正好相反
Pick<T, K extends keyof T>从 T 中摘取部分属性Pick<{ a: number, b: string, c: boolean }, 'a' | 'c'> <===> { a: number, c: boolean }
Omit<T, K extends keyof T>从 T 中排除部分属性Omit<{ a: number, b: string, c: boolean }, 'a' | 'c'> <===> { b: string }
Exclude<T, U>从 T 中剔除可以赋值给 U 的类型Exclude<number | string | boolean, string> <===> number | boolean
Extract<T, U>提取 T 中可以赋值给 U 的类型Exclude<number | string | boolean, string> <===> string
Record<K, T>返回属性名为 K,属性值为 T 的类型Record<'a' | 'b', () => void> <===> { a: ()=>void, b: ()=>void }
NonNullable<T>T 中剔除 nullundefinedNonNullable<string | null | undefined> <===> string
ConstructorParameters<T>获取 T 的构造函数参数类型组成的元组Compare是类,构造函数constructor(a: number, b:number){ ... }ConstructorParameters<typeof Compare> <===> [ a: number, b: number]
InstanceType<T>由构造函数类型T的实例类型来构建一个新类型InstanceType<typeof Compare> <===> Compare
Parameters<T>获取函数参数类型组成的元组Parameters<(a: number, b: string) => number> <===> [ a: number, b: number]
ReturnType<T>获取函数返回值类型ReturnType<(a: number, b: string) => number> <===> number

上面这些内置的工具类型能够很大程度上简化代码。

比如说给定一个interface接口,需要将内部所有属性都变成可选类型

虽然我们自己也可以写,但是如果直接使用现有的内置工具类型Partial不是更好么

interface A {
    name: string,
    age: number,
    action: ()=>void
}
type PartialFun<T> = {
    [K in keyof T] ? : T[K]
}
type _A = PartialFun<A>

或者说我在网上看到的一道转换题目:

  • 如何定义一个SetOptional工具类型,支持把给定的keys对应的属性变成可选的?
type Foo = {
	a: number;
	b?: string;
	c: boolean;
}

// 测试用例
type SomeOptional = SetOptional<Foo, 'a' | 'b'>;

这样在修改时思考方式,需要对Fooa | b匹配的属性拆除来变成可选,然后不匹配的属性维持不变,最后将可选和不可选通过& 进行联合

// 对应的属性变成可选
type CommonFun<T, K> = {
    [ t in keyof T as t extends K ? t: never] ?: T[t]
}
// 不对应的属性
type Unequal<T, K> = {
    [ t in keyof T as t extends K ? never: t] : T[t]
}
type SetOptional<T, K> = CommonFun<T, K> & Unequal<T, K> 

不过这样虽然思路很清晰,但是看起来写了好多。事实上,可以使用PartialPick来代替CommonFun, 然后用Omit代替Unequal

只需要像下面的一句就可以解决,是不是缩减了很多代码

type SetOptional<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K> 

当然这些都是要基于对typescript内置类型比较熟悉的情况下,最好的方式就是多多去使用。就像当初最开始学习javascript时,对于Math.floorsplice这些方法也是多使用才能够熟悉起来。

当然上面的这些例子可能会觉得实用性不大,那么将数组类型扁平化总应该算有点实用性吧

[ number, [string], [ boolean, [ void, string ] ] ] 转换成 number | string | boolean | void 扁平化联合

这种例子很容易就会想到**递归函数**

解决方案:首先使用infer X[]将当前数组中的元素进行判断,如果不是数组则直接返回,否则元素重新进入SetOptional判断循环。

type ArrType = [ number, [string], [ boolean, [ void, string ] ] ]

type SetOptional<T> = T extends (infer X)[] ? SetOptional<X> : T
// string | number | boolean | void
type Res = SetOptional<ArrType>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值