typescript 在打字稿中 <T> 是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49622045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Typescript what does <T> mean?
提问by Snorlax
export declare function createEntityAdapter<T>(options?: {
selectId?: IdSelector<T>;
sortComparer?: false | Comparer<T>;
}): EntityAdapter<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.
有人可以向我解释这是什么意思吗?我知道<>
是类型断言,但我不知道是什么'T'
。如果有人可以向我解释这个函数在做什么,这也会很有帮助。
回答by Erik Philips
Can someone explain to me what
<T>
the means?
有人可以向我解释这是什么
<T>
意思吗?
That is typescripts Genericsdeclaration.
那是打字稿泛型声明。
Excerpt:
摘抄:
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.
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.
软件工程的一个主要部分是构建不仅具有明确定义和一致的 API,而且还可以重用的组件。能够处理当前数据和未来数据的组件将为您提供构建大型软件系统的最灵活的功能。
在像 C# 和 Java 这样的语言中,工具箱中用于创建可重用组件的主要工具之一是泛型,即能够创建一个可以在多种类型上而不是单一类型上工作的组件。这允许用户使用这些组件并使用他们自己的类型。
You mentioned:
你提到:
I don't know what 'T' is.
我不知道“T”是什么。
'T'
is going to be a type declared at run-time instead of compiletime. 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 TContextor TEntityfor example).
'T'
将是在运行时而不是编译时声明的类型。该T
变量可以是任何非声明的变量(我无法找到一个参考,但我会承担任何有效的组可用于变量名的字符)。同样在c# 中,如果类型T
表示的不是值类型而是更复杂的类型(类)或接口,则可以将其命名/声明为TVehicle
或TAnimal
帮助表示未来程序员的有效类型(并且可以被视为最佳实践,因为只是T
不直观)。我更喜欢,TSomething
因为我知道大写 T 表示泛型类型。 WSometing
或者ASomething
也是有效的,但我只是不喜欢它。(微软的 API 几乎总是TContext或例如TEntity)。
It'd also be helpful if someone could explain to me what this function is doing.
如果有人可以向我解释这个函数在做什么,这也会很有帮助。
Well the function isn't doinganything. 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;
}
which can be used like:
可以像这样使用:
// type of output will be 'string'
let output = identity<string>("myString");
or
或者
// type of output will be 'string', the compiler will figure out `T`
// based on the value passed in
let output = identity("myString");
or
或者
// type of output will be 'number'
let output = identity(8675309);
Which might beg the question:
这可能会引出一个问题:
Why use generics
为什么要使用泛型
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:
Javascript 有数组,但是当你从数组中检索一个值时,它实际上可以是任何东西(打字稿:)any
。使用打字稿,您可以通过如下声明来获得类型安全:
// Array<T>
let list: number[] = [1, 2, 3];
// or
let list: Array<number> = [1, 2, 3];
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:
现在数组中的每个值都有一个类型。如果您尝试将字符串放入此数组,Typescript 将引发编译时错误。当您检索值时,您将获得类型安全和智能感知(取决于您的编辑器):
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.
声明类型化的泛型约束。开闭原则的一个很好的例子。
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.
在面向对象编程中,开放/封闭原则指出“软件实体(类、模块、函数等)应该对扩展开放,对修改封闭”;[1] 也就是说,这样的实体可以允许其行为在不修改其源代码的情况下进行扩展。
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.
在以下示例中,任何人都可以扩展 Human 或 Cheetah,甚至可以创建自己的派生类型,并且 Logger 功能无需任何修改即可继续工作。
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);
In the previous example I used a Generic Constraintto 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
.
在前面的示例中,我使用了通用约束来限制TAnimal
程序员可以用来创建Logger
从接口派生的类型的实例的类型IAnimal
。这允许编译器验证Logger
该类始终假定该类型具有属性LegCount
。
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> 而不是像 <Identity> 这样更具描述性的内容。没有什么和 <T> 对我来说是一样的。现在每个人都像傻瓜一样使用 <T> ,还是我错过了什么?
These are all going to be assumptions in the following. I do not know neither the team who designed the typescript generic system nor the team who wrote the documentation.
在下文中,这些都将是假设。我不知道设计 typescript 通用系统的团队和编写文档的团队。
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:
泛型的根本级别是能够T
用作任何可能的类型(不要与 typescript 混淆any
)。意义Array<T>
是接口(因为没有更好的词),当我们创建一个具体类型时,我们T
用一个声明的类型替换:
Array<number>
So for the interfaceArray<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 typeor Typebecame 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.
那么对于界面来说,Array<T>
还有什么比T
? 我不知道。我知道它T
必须是一个类型(数字、字符串等),所以使用它是有意义的,T
因为它是单词Type的第一个字母。我认为Array<Type>
如果type或Type被保留或限制(目前type
在某些上下文中具有特殊含义,因此这也是一个糟糕的选择),那将非常令人困惑和/或什至可能无效,因此避免这些是一个不错的选择。其他语言(C-sharp、Java)也选择使用T
,因此在语言之间切换并且能够使用相同的术语是有利的。
On the flip side what would the following mean?
另一方面,以下是什么意思?
Array<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.
什么是Identity
在这里吗?没有限制可以帮助其他开发人员或未来的开发人员了解它是什么。在我看来,它是一个我必须显式实现的特定类型化数组,这意味着我不能选择泛型类型。
interface Foo1 {
bars: Array<Identity>;
}
In the previous example, I (and probably most developers) would assume that Identity is an existing type and I cannot change it.
在前面的示例中,我(可能还有大多数开发人员)会假设 Identity 是现有类型并且我无法更改它。
interface Foo2<T> {
bars: Array<T>;
}
With Foo2
I know I have to choose a type.
随着Foo2
我知道我必须选择一个类型。
interface Foo3<Identity> {
bars: Array<Identity>;
}
Foo3
is just confusing.
Foo3
只是令人困惑。
interface Foo4<TIdentity> {
bars: Array<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.
现在有了Foo4
,我更有信心必须选择类型,但我仍然有点困惑为什么TIdentity
。显然,在某些情况下,类型更明确,这是有道理的。
回答by Emily Parker
The example you provide is a function with a generic parameter.
T
(which does not have to be T
. You could call it G
.) is called a generic template where actual type of the T
is replaced at runtime.
您提供的示例是一个带有泛型参数的函数。
T
(不一定是T
。您可以调用它G
。)被称为通用模板,其中 的实际类型T
在运行时被替换。
Imagine EntityAdapter has following implementation:
想象一下 EntityAdapter 有以下实现:
interface EntityAdapter<T> {
save(entity: T);
}
Below code returns an EntityAdapter which content is any
. any
could be number,string, object or anything.
下面的代码返回一个 EntityAdapter ,其内容是any
。any
可以是数字、字符串、对象或任何东西。
let adapter1 = createEntityAdapter<any>(<parameters here>)
Below code returns an EntityAdapter which content is Car
.
下面的代码返回一个 EntityAdapter ,其内容是Car
。
let adapter2 = createEntityAdapter<Car>(<parameters here>)
Basically Car
is more specific than any
so that you can get extra type safety. So how does this help?
基本上Car
比any
这样你可以获得额外的类型安全更具体。那么这有什么帮助呢?
In a nutshell, generic template can give you extra type safety. For example,
简而言之,通用模板可以为您提供额外的类型安全性。例如,
adapter1.save('I am string') // this works because `T` is `any`
adapter1.save(new Car()) // this also works because `T` is `any`
adapter2.save('I am string') // this wont works because `T` is `Car`, typescript compiler will complains
adapter2.save(new Car()) //this works because `T` is `Car`
Hope this helps.
希望这可以帮助。