简体   繁体   English

Typescript(真的)是否遵循 Generics 中参数化类型(T、U、V、W)的命名约定?

[英]Does Typescript (really) follows the naming convention for parameterized types (T, U, V, W) in Generics?

I am not exactly sure if in TS we follow this naming convention for parameterized types as C++/Java or many other languages ( T,U,V,W ).我不确定在 TS 中我们是否遵循 C++/Java 或许多其他语言( T,U,V,W )等参数化类型的命名约定。

I saw many times a mixed usage of parameterized types conventions in TS.我多次看到 TS 中参数化类型约定的混合使用。 For example, in the release notes of TS 2.8 :例如,在TS 2.8 的发行说明中

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

Why R and not U ?为什么R而不是U

then, in the next example:然后,在下一个示例中:

type Unpacked<T> = T extends (infer U)[]
  ? U
  : T extends (...args: any[]) => infer U
  ? U
  : T extends Promise<infer U>
  ? U
  : T;

Why U and not R ?为什么是U而不是R

Another example, in the same code block of the code just above:另一个示例,在上面代码的同一代码块中:

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

But in the TS source code:但是在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, ... }

The questions above are just examples to make a point, you don't need to answer them.上面的问题只是说明问题的例子,你不需要回答它们。 I could add some other examples where U is treated sometimes like the return type and sometimes is just a second type.我可以添加一些其他示例,其中U有时被视为返回类型,有时只是第二种类型。

My real question is: are we (really) following Java Generic Types convention for TS Generics?我真正的问题是:我们(真的)是否遵循 TS Generics 的Java 通用类型约定 If not, what kind of convention(s) does TS follows for Generics?如果不是,TS 对 Generics 遵循什么样的约定? How many different Type conventions are co-existing in TS (other than the obvious PascalCase for Type name and camelCase for type properties/methods)? TS 中共存了多少种不同的类型约定(除了类型名称的明显 PascalCase 和类型属性/方法的 camelCase)?

(From the comments, mostly) (主要来自评论)

The closest I can imagine answering this in any way which is not just my opinion would be to point to some documentation that describes what the "TypeScript Type Parameter Naming Convention" is and compare it to the Java Generics tutorial document you linked.我能想到的最接近的回答这个不仅仅是我的观点,是指向一些描述“TypeScript 类型参数命名约定”是什么的文档,并将其与您链接的Java Generics 教程文档进行比较。

If so, the TypeScript design team's official stance on this seems to be "we do not intend to impose any such conventions on others", or "there are no canonical naming conventions in TS".如果是这样,TypeScript设计团队对此的官方立场似乎是“我们不打算将任何此类约定强加给其他人”,或者“TS中没有规范的命名约定”。 See microsoft/TypeScript#6168 and microsoft/TypeScript#878 , specifically this comment :请参阅microsoft/TypeScript#6168microsoft/TypeScript#878 ,特别是此评论

[I]n general we're not interested in deciding stylistic things for people. [我]一般来说,我们对为人们决定风格的东西不感兴趣。 Saying that there's One Approved Style for TS goes against our philosophy that we're here to provide types for JS regardless of how you're writing it (within reasonable parameters, of course ).说 TS 有一种被批准的样式违背了我们的理念,即我们在这里为 JS 提供类型,无论您如何编写它(当然,在合理的参数范围内)。

There's also ESLint's naming-convention rule and TSLint's naming-convention rule , which make it possible to enforce type parameter naming conventions in a linter-checked code base, but do not seem to do by default .还有ESLint 的naming-convention规则TSLint 的naming-convention规则,这使得在经过 linter 检查的代码库中强制执行类型参数命名约定成为可能,但默认情况下似乎没有这样做。 So no convention seems to be official enough to be enforced by default.因此,似乎没有任何约定足够正式,可以默认强制执行。


For comparison's sake, let's take a look at the relevant section from the Java Generics tutorial document you linked:为了比较起见,让我们看一下您链接的 Java Generics 教程文档中的相关部分:

Type Parameter Naming Conventions类型参数命名约定

By convention, type parameter names are single, uppercase letters.按照惯例,类型参数名称是单个大写字母。 This stands in sharp contrast to the variable naming conventions that you already know about, and with good reason: Without this convention, it would be difficult to tell the difference between a type variable and an ordinary class or interface name.这与您已经知道的变量命名约定形成鲜明对比,并且有充分的理由:如果没有这个约定,就很难区分类型变量和普通 class 或接口名称之间的区别。

The most commonly used type parameter names are:最常用的类型参数名称是:

  • E - Element (used extensively by the Java Collections Framework) E - 元素(被 Java Collections 框架广泛使用)
  • K - Key K - 键
  • N - Number N - 数字
  • T - Type T - 类型
  • V - Value V - 价值
  • S,U,V etc. - 2nd, 3rd, 4th types S、U、V 等 - 第 2、第 3、第 4 类型

You'll see these names used throughout the Java SE API and the rest of this lesson.您将在本课的 Java SE API 和 rest 中看到这些名称。

Note that the enumerated list above is described as "the most commonly used type parameter names" and not "the only allowable type parameter names";请注意,上面列举的列表被描述为“最常用的类型参数名称”,而不是“唯一允许的类型参数名称”; it is a list of examples and thus descriptive and not prescriptive .它是一个示例列表,因此是描述性的而不是规定性的。

The part that about choosing "single, uppercase letters" is closer to a prescription: uppercase letters tend to distinguish type names from variable names, and single-character type names tend to distinguish type parameters from specific types like class or interfaces.关于选择“单个,大写字母”的部分更接近于处方:大写字母倾向于区分类型名和变量名,单字符类型名倾向于区分类型参数特定类型,如 class 或接口。 But I get the same sense that this is not so much a decree from on high but an observation about common practices.但我有同样的感觉,这与其说是来自上层的法令,不如说是对普遍做法的观察。


So we could presumably stop there and say "there is no official or canonical type parameter naming convention in either TypeScript or Java, and any unofficial such convention is a matter of opinion."所以我们大概可以停在那里说“在 TypeScript 或 Java 中没有官方或规范的类型参数命名约定,任何非官方的此类约定都是见仁见智的问题。”

But for the sake of trying to list out what I think the unofficial convention in TypeScript actually is , I'll go on.但为了试图列出我认为TypeScript 中的非官方约定实际上什么,我将打开 go。 Keep in mind that it's my opinion and people could plausibly disagree.请记住,这是我的意见,人们可能会不同意。


I'd say that the Java naming convention laid out above aligns pretty closely with what I would consider the de facto naming convention for TypeScript generic type parameters: use a single uppercase character, either corresponding to either the first letter of what they represent, such as:我想说的是上面列出的 Java 命名约定与我认为 TypeScript 泛型类型参数的实际命名约定非常接近:使用单个大写字符,或者对应于它们所代表的第一个字母,例如作为:

  • T for "type", the most general and therefore the most commonly used type parameter name; T代表“类型”,最通用也是最常用的类型参数名称;
  • K for "key", or P for "property", both of which tend to be constrained by PropertyKey or keyof T or keyof SomeInterface or keyof SomeClass ; K表示“key”,或P表示“property”,两者都倾向于受PropertyKeykeyof Tkeyof SomeInterfacekeyof SomeClass的约束;
  • V for "value", most commonly used as a pair with K for "key"; 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 ; 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 for "number", S for "string", B for "boolean, for type parameters constrained by primitives; N表示“数字”, S表示“字符串”, B表示“布尔值”,用于受基元约束的类型参数;

or some sequence of related types such as:或一些相关类型的序列,例如:

  • T , U , V , W , etc., starting with T for "type" and then walking through the alphabet when needing more types, keeping in mind that you can only get a few this way; TUVW等,从T开始表示“类型”,然后在需要更多类型时遍历字母表,请记住,您只能通过这种方式获得一些;
  • A , B , C , D , etc., starting from the beginning of the alphabet when you expect to use a whole bunch of type parameters and you haven't already used type parameters for something else. ABCD等,从字母表的开头开始,当您希望使用一大堆类型参数并且您还没有将类型参数用于其他用途时。

Such conventions are not absolute, and will tend to be bent where necessary to avoid ambiguity or other confusion.这样的约定不是绝对的,并且在必要时倾向于弯曲以避免歧义或其他混淆。 If you need more type parameters than can be obtained above without name collisions, it might be desirable to add a character to the name:如果您需要比上面没有名称冲突的类型参数更多的类型参数,则可能需要在名称中添加一个字符:

  • T0 , T1 , T2 , T3 , etc., appending numbers to get a sequence of related types; T0 , T1 , T2 , T3等,附加数字得到相关类型的序列;
  • KT , KU , KV : prefixing K for "keys of" T , U , and V , respectively; KTKUKV :分别为TUV的“键”添加前缀K

It is farther from what I consider conventional but still common enough to write short UpperCamelCase names to be more descriptive of what the types represent, with the drawback that they could start being confused for specific types and not type parameters:它与我认为的传统方式相去甚远,但仍然很常见,可以编写简短的 UpperCamelCase 名称以更好地描述类型所代表的内容,缺点是它们可能会开始混淆特定类型而不是类型参数:

  • Key , Val , Prop , Arg , Ret , Type , This Key , Val , Prop , Arg , Ret , Type , This

The following is unconventional (remember, my opinion here:) and should be avoided unless there is some overwhelming extenuating reason to do so:以下是非常规的(请记住,我的意见在这里:)并且应该避免,除非有一些压倒性的情有可原的理由这样做:

  • Long names that look like interface or class names like InputType or Properties ;看起来像 interface 或 class 名称的长名称,例如InputTypeProperties
  • Prefixing an uppercase T on a longer type name like TNotRecommended ;TNotRecommended等较长类型名称上添加大写T前缀;
  • Names that begin with a lowercase letter like t or u or myType ;以小写字母开头的名称,例如tumyType

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM