[英]Why generic T is inferred as a literal type only when it has a constraint?
請參閱以下代碼段
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
受約束(至少在此示例中)時發生?
有時候,你想確切的文本類型'hello'
推斷字符串文字'hello'
。 有時,您需要為字符串文字'hello'
推斷出更寬泛的非特定string
類型。
這些規則-什么時候應該推斷出確切的類型,什么時候應該擴大該類型-經過幾次迭代, 這里給出了當前的實現:
在調用表達式的類型實參推斷期間,如果滿足以下條件,則將針對類型形參T推斷的類型擴展為其擴展的文字類型:
- 對T的所有推論都是針對特定參數類型內T的頂級出現,以及
- T沒有約束,或者它的約束不包括原始或文字類型,並且
- T在推論期間是固定的,或者在返回類型的頂級不發生T。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.