给出一个函数,该函数接收相同泛型的两个参数:
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
再次,这两种用法为什么没有相同的行为?我希望这两种情况的行为都一样。
答案 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
您可以在*
周围添加更多特殊情况,这些特殊情况是使用对象文字初始化的,而该对象文字并未对其他内容进行类型声明,但这只会使事情变得更加不一致>