问题描述
查看以下代码片段
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
,唯一的区别是约束.
As you can see the bar
function infers the type of T
as a literal type ('111'
and 'hello'
in the example) but in the function foo
they are inferred as number
or string
, and the only difference is the constraint.
奇怪的是,如果使用盒装类型如下
Curiously, if use the boxed types as follows
declare function baz<T extends Number | String>(a: T): (b: T) => boolean;
then T
被推断为 number
和 string
,但它们中的一个是原始类型并且 T
被推断为文字类型:
then T
is inferred as number
and string
, but it's enough that one of them be a primitive type and T
is inferred as a literal type:
declare function brr<T extends Number | string>(a: T): (b: T) => boolean;
所以问题是: 为什么 foo('hello')
将 T
推断为 string
而 >bar('hello')
将 T
推断为 'hello'
?为什么它只在 T
被约束时发生(至少在这个例子中)?
So the question is: Why foo('hello')
infers T
as string
but bar('hello')
infers T
as 'hello'
? Why it happens only when T
is constrained (in this example at least)?
推荐答案
有时,您希望为字符串文字 'hello'
推断出精确的文字类型 'hello'
.有时,您希望为字符串文字 'hello'
推断出更广泛的、非特定的 string
类型.
Sometimes, you want exact literal type 'hello'
inferred for string literal 'hello'
. Sometimes, you want wider, non-specific string
type inferred for string literal 'hello'
.
规则 - 何时应该推断确切类型,何时应该扩大类型 - 经历了几次迭代,当前的实现 在此处显示:
The rules - when exact type should be inferred, and when the type should be widened - went through a couple of iterations, the current implemenation is presented here:
在调用表达式的类型参数推断期间,为类型参数 T 推断的类型扩展为其扩展的文字类型,如果:
- 对 T 的所有推断都是对特定参数类型中 T 的顶级出现进行的,并且
- T 没有约束或它的约束不包括原始类型或文字类型,并且
- T 是在推理过程中固定的,或者 T 没有出现在返回类型的顶层.
这篇关于为什么泛型 T 仅在具有约束时才被推断为文字类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!