将通用函数参数约束为通用接口类型

时间:2020-05-28 17:32:45

标签: typescript typescript-generics

在Typescript中,我有一个通用接口,表示要传递给函数的类型。

//foo must be an object {}, not a number or string or boolean or array
interface MyInterface<T extends {[key: string]: any}> {
  foo: T
}

所以我使函数通用,但TS不能从我的界面中推断约束

const myGenericFn: <T, U extends MyInterface<T>>(bar: U) => void = (bar) => {
  //Why is T not constrained to {[key: string]: any}? 
  //Shouldn't the constraint be inferred from MyInterface<T>?
  // Or be an error since T doesn't extend {[key: string]: any}?


  //bar.foo is T but T does not extend {[key: string]: any}! 
  const baz = bar.foo

}

//No error! Should be constrained to {foo: {[key: string]: any}} but accepts {foo: string}!
myGenericFn({foo: "bar"})

我能看到的唯一方法就是像这样重复对T的约束

const myGenericFnNotDRY: <T extends {[key: string]: any}, U extends MyInterface<T>>(bar: U) => void = (bar) => {
  //Not DRY, I have to repeat my generic constraint everywhere I want to use MyInterface within a generic fn!

  //bar.foo now correctly extends {[key: string]: any}
  const baz = bar.foo
}

//Errors as expected, string not assignable to {[key: string]: any}
myGenericFnNotDRY({foo: "bar"})

这似乎是TS中的一个大漏洞-它在不告诉我的情况下默默地删除了类型约束。这很容易导致很难跟踪错误。我可能在这里缺少一些基本概念。

TS Playground for above code

TS为什么不从MyInterface推断对T的约束?如何键入我的函数,以便将T正确地约束到MyInterface上特定的约束?

1 个答案:

答案 0 :(得分:0)

我建议做以下两件事之一:

TP / (TP + FP)

TypeScript游乐场是here