带有递归、条件和匹配键的TypeScript泛型
我有以下类型和2个通用参数:带有递归、条件和匹配键的TypeScript泛型,typescript,generics,typescript-generics,Typescript,Generics,Typescript Generics,我有以下类型和2个通用参数: type Result<INPUT, SPEC> = ... 简言之: 如果INPUT和SPEC是对象,那么Result应该是具有INPUT键的对象 对于INPUT的每个键:检查SPEC是否包含相同的键 如果true,则此键的值为Result 如果false,则此键的值为true 其他信息: 如果INPUT和SPEC是对象,则SPEC是INPUT的子集。这意味着:INPUT可以是{foo:42,bar:42},但是SPEC只允许包含foo或bar
type Result<INPUT, SPEC> = ...
简言之:
- 如果
和INPUT
是对象,那么SPEC
应该是具有Result
键的对象INPUT
- 对于
的每个键:检查INPUT
是否包含相同的键SPEC
- 如果
,则此键的值为true
Result
- 如果
,则此键的值为false
true
- 如果
和INPUT
是对象,则SPEC
是SPEC
的子集。这意味着:INPUT
可以是INPUT
,但是{foo:42,bar:42}
只允许包含SPEC
或foo
或两者都可以,或者为空bar
这在TypeScript中可能吗?根据您的描述,这种类型应该可以做到:
export type Result<INPUT, SPEC> = INPUT extends object ? SPEC extends object ? {
[K in keyof INPUT]: SPEC extends Record<K, infer SPECK> ?
Result<INPUT[K], SPECK> :
true
} : never : never;
// r is { foo: true; bar: never; goo: { a: never; b: true; }; }
type r = Result<{
foo: number,
bar: string,
goo: { a: number; b: string }
}, { bar: number, goo: { a: number }}>
导出类型结果=输入扩展对象?规格扩展对象?{
[K in keyof INPUT]:规格扩展记录?
结果:
真的
}:从不:从不;
//r是{foo:true;bar:never;goo:{a:never;b:true;};}
类型r=结果
您可能缺少的部分是SPEC extends Record
,此测试类型是否使用键K
扩展记录,并将该键的类型放入SPECK
您没有明确说明在else分支上发生了什么(如果任何一个类型参数都不是对象,那么我将never
放在那里,但您可以根据需要进行自定义)
如果没有100%正确,请告诉我,我们可以根据需要进行调整。Btw。看起来TypeScript知道扩展记录的含义。您应该能够编写以下内容:
SPEC扩展记录?结果
@BenjaminM编译器不理解记录
本身,它理解它下面的映射类型并找出键之间的关系。但你是对的,你的方式也很有效
export type Result<INPUT, SPEC> = INPUT extends object ? SPEC extends object ? {
[K in keyof INPUT]: SPEC extends Record<K, infer SPECK> ?
Result<INPUT[K], SPECK> :
true
} : never : never;
// r is { foo: true; bar: never; goo: { a: never; b: true; }; }
type r = Result<{
foo: number,
bar: string,
goo: { a: number; b: string }
}, { bar: number, goo: { a: number }}>