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

标签 typescript generics

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

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

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

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

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

同样,这两种用法怎么没有相同的行为?我希望这两种情况的行为相同。

最佳答案

此行为的引人注目的用例来自这样的示例,其中您有一些候选类型集,没有一个是其他类型的父类(super class)型,但预期的推断类型参数 ({ 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 });

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

当你有一些 binding foo 和一些类型 T 时,TypeScript 不能*知道 指向的对象foo 具有完全 T 类型 - 它可能具有更多 T 中未声明的属性>,但最终通过子类型关系绑定(bind)到 foo。这在实践中很常见。

因此,在 OP 的示例中,推断类型 { foo?: number, bar?: number } 是不合理的,因为 obj 可能指向到具有 string 类型的 bar 属性的对象。

* 您可以在 const 周围添加更多特殊情况,这些情况是使用未类型断言的对象文字初始化的,但这只会使事情更加不一致

关于TypeScript:具有相同泛型类型的多个参数的函数的混合行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56603747/

相关文章:

typescript - 如何从 typescript 中的另一个文件调用函数?

TypeScript Generic Factory Function Type,匹配数组元素顺序

javascript - 如何使用 Node 和 TypeScript 获取异步堆栈跟踪?

java - 从 String 变量实例化泛型类 (Java)

java - 为什么F<? extends Bar> 未分配给 F<Bar>

typescript - typescript 有自动属性吗?

javascript - 为什么输入在 React 生成时不起作用

c# - 类型可以解析字符串的通用类

swift - 无法转换类型的通用默认参数值

Java 静态方法中的泛型定义