TypeScript:具有多个相同泛型类型参数的函数的混合行为

时间:2019-06-14 18:53:04

标签: typescript generics

给出一个函数,该函数接收相同泛型的两个参数:

declare const fn: <T>(t1: T, t2: T) => any;

我试图推断当调用此函数时TypeScript具有不同的行为。

当两个参数都是两个不同的图元时:

fn(1, 'foo'); // Error due to different types

当2个参数都是两个对象时:

fn({ foo: 1 }, { bar: 1 }) // No error and return type is union of different types

这两种用法为什么没有相同的行为?我希望他们的行为都一样。要么:

  • 由于类型不同而导致的错误
  • 没有错误,返回类型是不同类型的并集

第二,如果传入的参数之一是变量(而不是内联对象文字),则TypeScript的行为会再次不同:

fn({ foo: 1 }, { bar: 1 }) // No error and return type is union of different types

const obj = { foo: 1 };
fn(obj, { bar: 1 }) // Error due to different types

再次,这两种用法为什么没有相同的行为?我希望这两种情况的行为都一样。

1 个答案:

答案 0 :(得分:1)

这种行为的引人注目的用例来自这样的示例,其中您有一些候选类型集,没有一个是其他类型的超类,但是预期的推断类型参数({ a?: number, b?: number, c?: number })很明显:

declare const fn: <T>(t1: T, t2: T, t3: T) => any;

fn({ a: 0, b: 1 }, { b: 2, c: 3 }, { a: 4, c: 5 });

当参数不是对象文字时,为什么不会发生这种情况?

当您具有某些类型为foo绑定 T时,TypeScript无法*知道foo所指向的对象具有完全是类型T-它可能​​具有更多属性,这些属性未在T中声明,但最终通过子类型绑定到foo关系。这在实践中很常见。

由于这个原因,在OP中的示例中,推断类型{ foo?: number, bar?: number }是不正确的,因为obj可能指向类型为{{1}的bar属性的对象}}。

string您可以在*周围添加更多特殊情况,这些特殊情况是使用对象文字初始化的,而该对象文字并未对其他内容进行类型声明,但这只会使事情变得更加不一致