【发布时间】:2019-04-06 06:27:59
【问题描述】:
看下面的sn-p
declare function foo<T>(a: T): (b: T) => boolean;
foo(111)(222); // T inferred as 'number'
foo('hello')('bye'); // T inferred as 'string'
declare function bar<T extends number | string>(a: T): (b: T) => boolean;
bar(111)(222); // T inferred as '111'
bar('hello')('bye'); // T inferred as 'hello'
如您所见,bar 函数将T 的类型推断为文字类型(示例中为'111' 和'hello'),但在函数foo 中,它们被推断为number 或string,唯一的区别就是约束。
奇怪的是,如果使用盒装类型如下
declare function baz<T extends Number | String>(a: T): (b: T) => boolean;
然后T 被推断为number 和string,但其中一个是原始类型并且T 被推断为文字类型就足够了:
declare function brr<T extends Number | string>(a: T): (b: T) => boolean;
所以问题是: 为什么foo('hello') 将T 推断为string 而bar('hello') 将T 推断为'hello'?为什么它只在T 受到约束时才会发生(至少在这个例子中)?
【问题讨论】:
-
当你说“为什么”时,你是在问背后的原因,还是在问 TypeScript 中的什么机制导致它发生?
-
顺便说一句,
Number | string推断数字文字可能是一个错误。似乎这种不一致的东西是“设计使然”的。 -
@PatrickRoberts 我在测试
Number | String时也有同样的想法,但是由于每个值都可以强制(在严格模式下)到包装的对象,然后是数字文字type 确实可以分配给“Number”。此外,这两种类型在函数内部将(大部分)无法区分。作为参考,这也适用于const n: Number = 42。尽管如此,这似乎很奇怪。