具有递归、条件和匹配键的 TypeScript 泛型

TypeScript Generics with recursion, conditionals and matching Keys

我有以下带有 2 个通用参数的类型:

type Result<INPUT, SPEC> = ...

Result的具体类型取决于INPUTSPEC的各种组合。

它应该如何工作:

if(INPUT extends {[key: string]: any}) {
  if(SPEC extends {[key: string]: any}) {
    Result = {[key in keyof INPUT]: SPEC[key] !== undefined
            ? Result<INPUT[key], SPEC[key]>
            : true
    }
  } else {
    // ...
  }
} else {
  // ...
}

换言之:

附加信息:

这在某种程度上可以用 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 }}>

您可能遗漏的部分是 SPEC extends Record<K, infer SPECK>,这会测试类型是否使用键 K 扩展记录并将该键的类型放入 SPECK

你没有明确说明在 else 分支上发生了什么(如果任何一个类型参数都不是对象,所以我把 never 放在那里,但你可以根据需要自定义)

如果我没有 100% 正确,请告诉我,我们可以根据需要进行调整。