TypeScript中K extends keyof T与带默认值写法的区别
两种
MyReadonly2泛型写法的差异 核心差异在于泛型参数K是否设置默认值,具体区别如下:
写法一:带默认值的泛型参数
type Exclude<T, K> = T extends K ? never : T type MyReadonly2<T, K extends keyof T = keyof T> = { readonly [P in K]: T[P] } & { [L in Exclude<keyof T, K>]: T[L] }
这里给K设置了默认值keyof T,带来两个特性:
- 调用时可省略第二个参数,此时
K自动取T的所有键,效果和原生Readonly<T>一致,直接把所有属性设为只读。 - 也能主动传入指定键,只将这些键设为只读,比如
MyReadonly2<{a: number, b: string}, 'a'>仅把a设为只读。
写法二:无默认值的泛型参数
type Exclude<T, K> = T extends K ? never : T type MyReadonly2<T, K extends keyof T> = { readonly [P in K]: T[P] } & { [L in Exclude<keyof T, K>]: T[L] }
这种写法里K没有默认值,限制很明确:
- 调用时必须显式传入第二个参数,否则TypeScript会报错,提示缺少泛型参数
K。 - 只能用于给指定的部分属性设置只读,要实现全属性只读,必须手动传入
keyof T。
举个使用对比:
- 写法一支持:
type FullReadonly = MyReadonly2<{x: number, y: string}>(自动全只读) - 写法二不支持上述用法,必须写成:
type FullReadonly = MyReadonly2<{x: number, y: string}, keyof {x: number, y: string}>
总结:写法一灵活性更高,兼顾部分只读和全只读场景;写法二仅适用于必须指定只读属性的场景。
内容的提问来源于stack exchange,提问作者Zachariah Ramiro
相关产品推荐
相关产品推荐

