【问题标题】:TypeScript: mixed behaviour for function with multiple parameters of same generic typeTypeScript:具有相同泛型类型的多个参数的函数的混合行为
【发布时间】:2019-10-29 10:05:18
【问题描述】:

给定一个接收相同泛型类型的两个参数的函数:

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

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

当 2 个参数都是不同的原语时

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

当两个参数都是不同的对象时

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

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

【问题讨论】:

标签: typescript generics


【解决方案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 可能已指向具有 bar 属性类型为 string 的对象。

* 你可以在 consts 周围添加更多特殊情况,这些情况是用一个没有类型断言的对象字面量初始化的,但这只会让事情变得更加不一致

【讨论】:

  • 感谢您解决这个问题!这就说得通了。我的问题的第一部分(原始与对象)怎么样?我不确定你是否涵盖了这一点,除非我遗漏了什么?或者也许可以在您在评论中链接到的 PR (github.com/microsoft/TypeScript/pull/19513) 中找到答案?
  • 原始行为和非新鲜对象行为相同;只有新鲜的物品才能得到特殊处理
猜你喜欢
  • 2021-12-15
  • 1970-01-01
  • 2023-02-09
  • 2010-10-04
  • 1970-01-01
  • 2017-03-07
  • 2021-06-11
  • 1970-01-01
相关资源
最近更新 更多