请参见以下代码段
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'
),但在函数{{1 }}推断为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')
为{{1} }?为什么仅在约束T
时才会发生这种情况(至少在此示例中如此)?
答案 0 :(得分:2)
有时,您需要为字符串文字'hello'
推断出确切的文字类型'hello'
。有时,您需要为字符串文字string
推断出更广泛的,非特定的'hello'
类型。
规则-什么时候应该推断出确切的类型,什么时候应该扩大类型-经历了几次迭代,当前的实现is presented here:
在调用表达式的类型实参推断期间,如果满足以下条件,则对类型参数T推断的类型将扩展为其扩展的文字类型。
- 所有针对T的推论都是针对特定参数类型内T的顶级出现,并且
- T没有约束,或者它的约束不包括原始或文字类型,并且
- T在推断过程中是固定的,或者在返回类型的顶级不发生T。