为什么泛型T仅在有约束时才被推断为文字类型?

时间:2018-11-02 00:48:56

标签: typescript type-inference

请参见以下代码段

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'

playground

您可以看到bar函数将T的类型推断为文字类型(在示例中为'111''hello'),但在函数{{1 }}推断为foonumber,唯一的区别是约束。

奇怪的是,如果使用如下所示的框式

string

然后将declare function baz<T extends Number | String>(a: T): (b: T) => boolean; 推断为Tnumber,但是只要将其中一个作为原始类型并将string推断为文字类型就足够了:

T

所以问题是:为什么declare function brr<T extends Number | string>(a: T): (b: T) => boolean; 推断foo('hello')Tstring推断bar('hello')为{{1} }?为什么仅在约束T时才会发生这种情况(至少在此示例中如此)?

1 个答案:

答案 0 :(得分:2)

有时,您需要为字符串文字'hello'推断出确切的文字类型'hello'。有时,您需要为字符串文字string推断出更广泛的,非特定的'hello'类型。

规则-什么时候应该推断出确切的类型,什么时候应该扩大类型-经历了几次迭代,当前的实现is presented here

  

在调用表达式的类型实参推断期间,如果满足以下条件,则对类型参数T推断的类型将扩展为其扩展的文字类型。

     
      
  • 所有针对T的推论都是针对特定参数类型内T的顶级出现,并且
  •   
  • T没有约束,或者它的约束不包括原始或文字类型,并且
  •   
  • T在推断过程中是固定的,或者在返回类型的顶级不发生T。
  •