在打字稿中 <T>意思? [英] In Typescript what does <T> mean?

查看:33
本文介绍了在打字稿中 <T>意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

export declare function createEntityAdapter<T>(options?: {
    selectId?: IdSelector<T>;
    sortComparer?: false | Comparer<T>;
}): EntityAdapter<T>;

有人可以向我解释一下这是什么意思吗?我知道 <> 是类型断言,但我不知道 'T' 是什么.如果有人能向我解释这个函数在做什么,也会很有帮助.

Can someone explain to me what the means? I know <> is type assertion but I don't know what 'T' is. It'd also be helpful if someone could explain to me what this function is doing.

推荐答案

有人可以向我解释一下 是什么意思吗?

这是打字稿泛型声明.

摘录:

软件工程的一个主要部分是构建不仅具有明确定义且一致的 API,而且还可以重用的组件.能够处理当前数据和未来数据的组件将为您提供构建大型软件系统的最灵活的功能.

A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable. Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems.

在 C# 和 Java 等语言中,工具箱中用于创建可重用组件的主要工具之一是泛型,即能够创建可以在多种类型上工作的组件,而不是单一类型.这允许用户使用这些组件并使用他们自己的类型.

In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is generics, that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types.

你提到:

我不知道T"是什么.

'T' 将是在运行时而不是编译时声明的类型.T 变量可以是任何未声明的变量(我找不到引用,但我假设任何可用于变量名称的有效字符集).同样在 中,如果类型 T 代表的不是值类型而是更复杂的类型(类)或接口,可以命名/声明为 TVehicleTAnimal 以帮助表示一个对未来程序员有效的类型(并且可以被认为是最佳实践,因为 T 不直观).我更喜欢 TSomething 因为我知道大写 T 表示泛型类型.WSometingASomething 也是有效的,但我只是不喜欢它.(微软的 API 几乎总是 TContextTEntity 例如).

'T' is going to be a type declared at run-time instead of compile time. The T variable could be any non-declared variable (I couldn't find a reference, but I would assume any valid set of characters that could be used for a variable names). Similarly in c#, if the type T represents is not a value type but a more complex type (class) or interface, it could be named/declared as TVehicle or TAnimal to help denote a valid type for future programmers (and could be considered best practice because just T is not intuitive). I prefer TSomething because I know that uppercase T means a generic type. WSometing or ASomething is also valid, but I just don't prefer it. (Microsofts APIs are almost always TContext or TEntity for example).

如果有人能向我解释这个函数在做什么也会很有帮助.

It'd also be helpful if someone could explain to me what this function is doing.

好吧,这个函数没有任何事情.这更多地声明了一种可以具有多个运行时类型值的函数.我将直接从上面的链接中摘录一段,而不是解释这一点.

Well the function isn't doing anything. This is more declaring a type of function that can have multiple run-time type values. Instead of explaining that, I'll include an excerpt taken directly from the link above.

function identity<T>(arg: T): T {
  return arg;
}

可以像这样使用:

// type of output will be 'string'
let output = identity<string>("myString");  

// type of output will be 'string', the compiler will figure out `T`
// based on the value passed in
let output = identity("myString");  

// type of output will be 'number'
let output = identity(8675309);  

这可能会引出一个问题:

Which might beg the question:

为什么要使用泛型

Javascript 有数组,但是当你从数组中检索一个值时,它实际上可以是任何东西(打字稿:any).使用打字稿,您可以通过如下声明来获得类型安全:

Javascript has arrays, but when you retrieve a value from the array, it literally could be anything (typescript: any). With typescript you get Type safety by declaring them like:

 // Array<T>
 let list: number[] = [1, 2, 3];
 // or 
 let list: Array<number> = [1, 2, 3];

现在数组中的每个值都有一个类型.如果您尝试将字符串放入此数组,Typescript 将引发编译时错误.当您检索值时,您将获得类型安全和智能感知(取决于您的编辑器):

Now each value in the array has a type. Typescript will throw a compile-time error if you attempt to put a string into this array. And you get type-safety and intellisense (depending on your editor) when you retrieve a value:

class Person {
  FirstName: string;
}

let people: Array<Person> = [];
people.push({ FirstName: "John" } as Person);

let john = people.pop();  
// john is of type Person, the typescript compiler knows this
// because we've declared the people variable as an array of Person

console.log(john.FirstName);  

声明类型化的泛型约束.开放-封闭原则的一个很好的例子.

Declaring type'd generic constraints. A very good example of Open - Closed Principle.

在面向对象编程中,开放/封闭原则指出软件实体(类、模块、函数等)应该对扩展开放,对修改封闭";[1] 即,这样的实体可以允许在不修改其源代码的情况下扩展其行为.

In object-oriented programming, the open/closed principle states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification";[1] that is, such an entity can allow its behaviour to be extended without modifying its source code.

在以下示例中,任何人都可以扩展 Human 或 Cheetah,甚至可以创建自己的派生类型,并且 Logger 功能无需任何修改即可继续工作.

In the following example, anyone could extend Human or Cheetah or even create their own derived type and the Logger functionality would continue to work without any modification.

interface IAnimal {
  LegCount: number;
}

class Cheetah 
  implements IAnimal {
  LegCount: number = 4;
}

class Human
  implements IAnimal {
  LegCount: number = 2;
}

public class Logger<TAnimal extends IAnimal> {
  public Log(animal: TAnimal) {
    console.log(animal.LegCount);
  }
}
 
var logger = new Logger();
var human = new Human();
logger.Log(human);      

工作示例

在前面的示例中,我使用了通用约束将程序员可用于创建 Logger 实例的 TAnimal 类型限制为从接口 IAnimal 派生的类型.这允许编译器验证 Logger 类始终假定该类型具有属性 LegCount.

In the previous example I used a Generic Constraint to limit the TAnimal type programmers can use to create a Logger instance to types that derive from the interface IAnimal. This allows the compiler to validate that the Logger class always assume the type has a property LegCount.

你可以向我解释为什么他们在 Typescript 文档中放置了 <T>而不是像 <Identity> 这样更具描述性的东西.例如.什么都没有,<T>对我来说是一样的.现在是否每个人都使用 <T>像傻子一样,还是我错过了什么?

You can explain to me why in the Typescript documentation they put <T> instead of putting something more descriptive like <Identity> for example. Nothing and <T> for me is the same. Now does everyone use the <T> like fools, or did I miss something?

这些都是下面的假设.我不知道设计 typescript 通用系统的团队和编写文档的团队.

泛型的根本级别是能够将 T 用作任何可能的类型(不要与 typescript any 混淆).含义 Arrayinterface(因为没有更好的词),当我们创建一个具体类型时,我们将 T 替换为声明的类型:

At the root level of generics is the ability to use T as any possible type (not to be confused with typescript any). Meaning Array<T> is the interface (for lack of a better word) and when we create a concrete type we replace T with a declared type:

Array<number>

那么对于接口Array来说,有什么比T更有意义的?我不知道.我确实知道 T 必须是一个类型(数字、字符串等),所以使用 T 是有意义的,因为它是单词 Type 的第一个字母.我认为 Array 如果 typeType 被保留或限制(当前 type 在某些上下文中具有特殊含义,因此它也是一个糟糕的选择),因此避免使用它们是一个不错的选择.其他语言(C-sharpJava) 也选择使用 T,所以在语言之间切换并且能够使用相同的术语是有利的.

So for the interface Array<T> what makes more sense than T? I don't know. I do know that T has to be a Type (number, string, etc) so it makes sense to use T because it the first letter of the word Type. I think Array<Type> would be really confusing and/or might even be invalid if type or Type became reserved or restricted (currently type has special meaning in certain contexts so it's also a poor choice) so avoiding those is a good choice. Other languages (C-sharp, Java) also choose to use T, so switching between languages and being able to use the same term is advantageous.

另一方面,以下是什么意思?

On the flip side what would the following mean?

Array<Identity>

这里的 Identity 是什么?没有限制可以帮助其他开发人员或未来的开发人员了解它是什么.在我看来,它是一个我必须显式实现的特定类型数组,这意味着我不能选择泛型类型.

What is Identity here? There is no constraint to help other developers or future developers know what it is. It would appear to me to be a specific typed Array that I must implement explicitly, which means it's not up to me to choose the generic type.

interface Foo1 {
  bars: Array<Identity>;
}

在前面的示例中,我(可能还有大多数开发人员)会假设 Identity 是现有类型并且我无法更改它.

In the previous example, I (and probably most developers) would assume that Identity is an existing type and I cannot change it.

interface Foo2<T> {
  bars: Array<T>;
}

使用 Foo2 我知道我必须选择一种类型.

With Foo2 I know I have to choose a type.

interface Foo3<Identity> {
  bars: Array<Identity>;
}

Foo3 只是令人困惑.

interface Foo4<TIdentity> {
  bars: Array<TIdentity>;
}

现在有了 Foo4,我更有信心必须选择类型,但我仍然有点困惑为什么要选择 TIdentity.显然,在某些情况下,类型更明确,这会有意义.

Now with Foo4, I am much more confident that I must choose the type, but I'm still a bit confused why TIdentity. Obviously in some contexts, where the type is more defined, it would make sense.

截至 2021 年 3 月,Typescript 文档 已更新以弃用<T> 在文档中,有利于代替 .

As of March 2021, the Typescript Documentation has been updated to deprecate the use of <T> in documentation, in favor instead of <Type>.

既然如此,我个人发现以下内容令人困惑,强烈建议避免使用 Type 有两个原因.

That being the case, I personally find the following confusing and would highly suggest avoiding Type it for two reasons.

interface Lengthwise {
  length: number;
}

function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
  console.log(arg.length); 
  return arg;
}

在使用约束时避免将类型命名为 Type 的第一个原因是它在方法内和多个方法中都不能很好地读取.想象一下,日志记录方法比 2 行要长得多,而且突然之间你读到的只是Type 这个词.

The first reason to avoid naming your type Type when using constraints is that it doesn't read very well within the method nor with multiple methods. Imagine the logging methods are much longer than 2 lines, and all of a sudden all you're reading is the word Type everywhere.

interface Lengthwise {
  length: number;
}

interface Widthwise {
  width: number;
}

function loggingLength<Type extends Lengthwise>(arg: Type): Type {
  console.log(arg.length);
  return arg;
}

function loggingWidth<Type extends Widthwise >(arg: Type): Type {
  console.log(arg.width);
  return arg;
}

我认为以下内容更具可读性:

I think the following is much more readable:

interface Lengthwise {
  length: number;
}

interface Widthwise {
  width: number;
}

function loggingLength<TLengthwise extends Lengthwise>(arg: TLengthwise): TLengthwise {
  console.log(arg.length);
  return arg;
}

function loggingWidth<TWidthwise extends Lengthwise>(arg: TWidthwise ): TWidthwise {
  console.log(arg.length);
  return arg;
}

其次,很可能有超过 1 个泛型,这会使以下无效(希望出于明显的原因).

Secondly it's very possible to have more then 1 generic and that makes the following invalid (hopefully for obvious reasons).

interface Lengthwise {
  length: number;
}

interface Widthwise {
  width: number;
}

function loggingLength<Type extends Lengthwise, Type extends Widthwise>
(arg1: Type, arg2: Type) {
  console.log(arg1.length);
  console.log(arg2.width);
}

虽然文档使用 Type 来展示简单和平凡的例子,但我强烈建议不要在任何现实世界的代码中使用 Type.

While the documentation uses Type for showing off simplistic and mundane examples, I highly suggest not using Type in any real world code.

这篇关于在打字稿中 &lt;T&gt;意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆