TypeScript中如何禁止泛型参数存在额外属性?
TypeScript中如何禁止泛型参数存在额外属性?
我明白你的需求啦——你希望在调用Test泛型的时候,如果传入的第二个参数带有原类型T里没有的额外属性,直接在代码编写阶段就抛出错误,而不是靠后续让Result变成never来间接发现问题,对吧?
其实你遇到的问题是TypeScript结构类型系统的特性导致的:默认情况下,只要一个类型的属性包含目标类型的所有要求,就算多了额外属性也会被认为是兼容的。要禁止这种情况,我们需要给泛型参数P加上额外的约束,确保它的键完全匹配PartialRecursive<T>的键(也就是原类型T的所有键)。
下面是具体的实现方案:
type PartialRecursive<T> = { [K in keyof T]?: PartialRecursive<T[K]>; } // 修改Test泛型,添加额外约束限制键的范围 type Test<T, P extends PartialRecursive<T> & (keyof P extends keyof T ? unknown : never)> = T; // 测试案例:这里会直接报错,因为test2是额外属性 type Result = Test<{test: true}, {test: true, test2: {}}>;
我们来拆解一下这个约束的逻辑:
PartialRecursive<T>保持你原来的递归可选类型定义;keyof P extends keyof T ? unknown : never是关键:如果P的所有键都属于T的键,那么这个条件返回unknown(和PartialRecursive<T>交叉后不影响原有约束);如果P存在额外键,这个条件返回never,此时P需要同时extendsPartialRecursive<T>和never,自然就会触发类型错误。
另外还有一种等价的写法,利用Record类型来限制额外属性必须是never类型:
type Test<T, P extends PartialRecursive<T> & Record<Exclude<keyof P, keyof T>, never>> = T;
这个写法的逻辑是:用Exclude<keyof P, keyof T>提取出P中不属于T的额外键,然后要求这些键对应的类型必须是never。而你传入的test2: {}显然不是never,所以会直接报错。
这样就能在代码编写阶段就检测到额外属性的问题,完全符合你的需求啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

