簡體   English   中英

為什么 Typescript 在給出擴展類型的泛型時可以獲得確切的值

[英]Why Typescript can get the exact value when giving a Generics that extends types

正常用法:

我只有字符串[]

function getResult<T>(...v: T[]) {
  return v
}

const str = getResult('str', 'str2') // const str: string[]

// or even
const str = getResult<string>('str' as const, 'str2') // const str: string[]

但是如果我讓泛型擴展字符串,最終會得到:

// for stirng
function getResultByExtendsString<T extends string>(...v: T[]) {
  return v
}

const str2 = getResultByExtendsString('str', 'str2') // const str2: ("str" | "str2")[]

// for number
function getResultByExtendsNumber<T extends number>(...v: T[]) {
  return v
}

const num2 = getResultByExtendsNumber(123, 456) // const num2: (123 | 456)[]

甚至混合類型

但是如果我刪除 P、Q 的擴展,它不會得到值,而是它的類型

type Types = string | number

function getAllResults<P extends Types, Q extends Types>(p: P, v: Q): (P | Q)[] {
  return [p, v]
}

const res = getAllResults('str', 123) // const res: ("str" | 123)[]

那么這是怎么發生的呢?

謝謝。 ts背景看

這可以通過編譯器的“上下文類型”功能來確定。 即使您在等式的一側(即函數)只有類型,TypeScript 編譯器也可以確定類型。 通用類 | 功能 | 如果數據類型未知或“復雜”,則變量通常用作“復雜”類型。

資源:

https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html#types-by-inference

https://www.typescriptlang.org/docs/handbook/functions.html#inferring-the-types

這是microsoft/TypeScript#10676 “始終使用文字類型”的結果。 一般來說,編譯器最初總是為字符串、數字或布爾值推斷最窄的文字類型。 所以"str"被視為類型"str"

但是,編譯器會經常(但不總是)擴展類型,這取決於它的使用方式。 所以有時類型"str"被擴展為string 而其他時候它會保持"str" 上面鏈接的拉取請求經歷了許多不同的情況,其中一種行為或另一種行為發生(例如, const str = "str";未加寬,但let str = "str"加寬),並且您可以粗略地說類型被加寬,除非編譯器知道您期望更窄的類型。

但特別是,與此問題相關的啟發式方法是當您調用泛型函數時編譯器如何推斷類型參數:

在調用表達式的類型參數推斷期間,為類型參數 T 推斷的類型擴展為其擴展的文字類型,如果:

  • 對 T 的所有推斷都是對特定參數類型中 T 的頂級出現進行的,並且
  • T 沒有約束或其約束不包括原始類型或文字類型,並且
  • T 在推理過程中是固定的,或者 T 不會出現在返回類型的頂層。

因此,如果T沒有約束,如getResult<T>(...) ,或者如果約束不包括原始類型或文字類型,如getSomethingElse<T extends Date>(...)T將被加寬。 因此,對於那些調用,您將獲得stringnumber而不是字符串或數字文字。

但是在存在包含原始類型的約束的情況下,例如getResultByExtendsString<T extends string>(...)getResultByExtendsNumber<T extends number>(...) ,甚至getAllResults<P extends Types, Q extends Types>(...) (因為Types包括stringnumber ),類型沒有加寬。 所以"str"123將保持"str"123

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM