[英]Does Typescript (really) follows the naming convention for parameterized types (T, U, V, W) in Generics?
我不確定在 TS 中我們是否遵循 C++/Java 或許多其他語言( T,U,V,W
)等參數化類型的命名約定。
我多次看到 TS 中參數化類型約定的混合使用。 例如,在TS 2.8 的發行說明中:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
為什么R
而不是U
?
然后,在下一個示例中:
type Unpacked<T> = T extends (infer U)[]
? U
: T extends (...args: any[]) => infer U
? U
: T extends Promise<infer U>
? U
: T;
為什么是U
而不是R
?
另一個示例,在上面代碼的同一代碼塊中:
type T0 = Unpacked<string>; // string
type T1 = Unpacked<string[]>; // string
type T2 = Unpacked<() => string>; // string
type T3 = Unpacked<Promise<string>>; // string
type T4 = Unpacked<Promise<string>[]>; // Promise<string>
type T5 = Unpacked<Unpacked<Promise<string>[]>>; // string
但是在TS源代碼中:
// We represent tuple types as type references to synthesized generic interface types created by
// this function. The types are of the form:
//
// interface Tuple<T0, T1, T2, ...> extends Array<T0 | T1 | T2 | ...> { 0: T0, 1: T1, 2: T2, ... }
上面的問題只是說明問題的例子,你不需要回答它們。 我可以添加一些其他示例,其中U
有時被視為返回類型,有時只是第二種類型。
我真正的問題是:我們(真的)是否遵循 TS Generics 的Java 通用類型約定? 如果不是,TS 對 Generics 遵循什么樣的約定? TS 中共存了多少種不同的類型約定(除了類型名稱的明顯 PascalCase 和類型屬性/方法的 camelCase)?
(主要來自評論)
我能想到的最接近的回答這個不僅僅是我的觀點,是指向一些描述“TypeScript 類型參數命名約定”是什么的文檔,並將其與您鏈接的Java Generics 教程文檔進行比較。
如果是這樣,TypeScript設計團隊對此的官方立場似乎是“我們不打算將任何此類約定強加給其他人”,或者“TS中沒有規范的命名約定”。 請參閱microsoft/TypeScript#6168和microsoft/TypeScript#878 ,特別是此評論:
[我]一般來說,我們對為人們決定風格的東西不感興趣。 說 TS 有一種被批准的樣式違背了我們的理念,即我們在這里為 JS 提供類型,無論您如何編寫它(當然,在合理的參數范圍內)。
還有ESLint 的naming-convention
規則和TSLint 的naming-convention
規則,這使得在經過 linter 檢查的代碼庫中強制執行類型參數命名約定成為可能,但默認情況下似乎沒有這樣做。 因此,似乎沒有任何約定足夠正式,可以默認強制執行。
為了比較起見,讓我們看一下您鏈接的 Java Generics 教程文檔中的相關部分:
類型參數命名約定
按照慣例,類型參數名稱是單個大寫字母。 這與您已經知道的變量命名約定形成鮮明對比,並且有充分的理由:如果沒有這個約定,就很難區分類型變量和普通 class 或接口名稱之間的區別。
最常用的類型參數名稱是:
- E - 元素(被 Java Collections 框架廣泛使用)
- K - 鍵
- N - 數字
- T - 類型
- V - 價值
- S、U、V 等 - 第 2、第 3、第 4 類型
您將在本課的 Java SE API 和 rest 中看到這些名稱。
請注意,上面列舉的列表被描述為“最常用的類型參數名稱”,而不是“唯一允許的類型參數名稱”; 它是一個示例列表,因此是描述性的而不是規定性的。
關於選擇“單個,大寫字母”的部分更接近於處方:大寫字母傾向於區分類型名和變量名,單字符類型名傾向於區分類型參數和特定類型,如 class 或接口。 但我有同樣的感覺,這與其說是來自上層的法令,不如說是對普遍做法的觀察。
所以我們大概可以停在那里說“在 TypeScript 或 Java 中沒有官方或規范的類型參數命名約定,任何非官方的此類約定都是見仁見智的問題。”
但為了試圖列出我認為TypeScript 中的非官方約定實際上是什么,我將打開 go。 請記住,這是我的意見,人們可能會不同意。
我想說的是上面列出的 Java 命名約定與我認為 TypeScript 泛型類型參數的實際命名約定非常接近:使用單個大寫字符,或者對應於它們所代表的第一個字母,例如作為:
T
代表“類型”,最通用也是最常用的類型參數名稱;K
表示“key”,或P
表示“property”,兩者都傾向於受PropertyKey
或keyof T
或keyof SomeInterface
或keyof SomeClass
的約束;V
表示“值”,最常與K
表示“鍵”成對使用;A
for "arguments" and R
for "return", corresponding to the rest parameter list and return type of function signatures respectively, like (...args: A) => R
;N
表示“數字”, S
表示“字符串”, B
表示“布爾值”,用於受基元約束的類型參數;或一些相關類型的序列,例如:
T
, U
, V
, W
等,從T
開始表示“類型”,然后在需要更多類型時遍歷字母表,請記住,您只能通過這種方式獲得一些;A
, B
, C
, D
等,從字母表的開頭開始,當您希望使用一大堆類型參數並且您還沒有將類型參數用於其他用途時。這樣的約定不是絕對的,並且在必要時傾向於彎曲以避免歧義或其他混淆。 如果您需要比上面沒有名稱沖突的類型參數更多的類型參數,則可能需要在名稱中添加一個字符:
T0
, T1
, T2
, T3
等,附加數字得到相關類型的序列;KT
、 KU
、 KV
:分別為T
、 U
和V
的“鍵”添加前綴K
;它與我認為的傳統方式相去甚遠,但仍然很常見,可以編寫簡短的 UpperCamelCase 名稱以更好地描述類型所代表的內容,缺點是它們可能會開始混淆特定類型而不是類型參數:
Key
, Val
, Prop
, Arg
, Ret
, Type
, This
以下是非常規的(請記住,我的意見在這里:)並且應該避免,除非有一些壓倒性的情有可原的理由這樣做:
InputType
或Properties
;TNotRecommended
等較長類型名稱上添加大寫T
前綴;t
或u
或myType
;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.