typescript泛型_TypeScript中的泛型
typescript泛型
Following the DRY principle, one should write dynamic and reusable code. Generics are not a new term in the programming language. In fact, it follows the DRY principle very well.
遵循DRY原理,应该编写动态且可重用的代码。 泛型不是编程语言中的新术语。 实际上,它很好地遵循了DRY原理。
Generics in TypeScript come in handy. You can write beautiful, dynamic, and reusable generic blocks of code using generics. Furthermore, you can apply generics in TypeScript to classes
, interfaces
, and functions
.
TypeScript中的泛型派上用场。 您可以使用泛型编写漂亮,动态和可重用的通用代码块。 此外,您可以将TypeScript中的泛型应用于classes
, interfaces
和functions
。
什么是泛型? (What are Generics?)
Sometimes you come across a situation to repeat the same block of code for different types. So, instead of writing repeated blocks of code, generics let you write a generalized form of method.
有时您遇到一种情况,需要针对不同类型重复相同的代码块。 因此,泛型使您无需编写重复的代码块,而可以编写一种通用形式的方法。
Although, there is a type called any
, which you can use to achieve the same effect as generics in your code, any
is not type-safe
, and chances are that your application can get an exception.
尽管有一个名为any
的类型,您可以使用它来实现与代码中的泛型相同的效果,但是any
不是type-safe
,并且很可能您的应用程序会获得异常。
To clarify, take a look at the below example to better understand the above case.
为了清楚起见,请看以下示例,以更好地理解上述情况。
// for number type
function fun(args: number): number {
return args;
}
// for string type
function fun(args: string): string {
return args;
}
Note that, here we are repeating the same function for number
and string
types. In this case, there is one way to make it generic –– using type any
.
注意,这里我们对number
和string
类型重复相同的功能。 在这种情况下,有一种使它通用的方法–使用any
类型。
To show, let’s see how to make it generic using type any
.
为了显示,让我们看看如何使用any
类型使其通用。
// for any type
function fun(args: any): any {
return args;
}
While swapping number
and string
types to type any
, we achieved our goal to make it generic, there’s a catch –– it can accept any kind of data and as a result, we are losing type safety as well.
在交换number
和string
类型以键入any
,我们实现了使其通用的目标,但有一个陷阱–它可以接受任何类型的数据,结果,我们也失去了类型安全性。
In short, the TypeScript compiler doesn’t know about its data type passed to this function.
简而言之,TypeScript编译器不知道传递给此函数的数据类型。
使它们成为类型安全 (Make Them Type-Safe)
To solve the above problem and make it type-safe again, we’ll use Type
parameters. Type
parameters are, generally, defined by T
or <T>
. They denote the data type of passed parameters to a class, interface, and functions.
为了解决上述问题并再次使其具有类型安全性,我们将使用Type
参数。 Type
参数通常由T
或<T>
定义。 它们表示传递给类,接口和函数的参数的数据类型。
To show, let’s use T
to make our generic function type-safe
.
为了说明这一点,让我们使用T
来使通用函数type-safe
。
function fun<T>(args:T):T {
return args;
}
As a result, it’s now type-safe. Let’s see how to use the same function for string
and number
type.
结果,它现在是类型安全的。 让我们看看如何对string
和number
类型使用相同的函数。
// for string
let result = fun<string>("Hello World");
// for number
let result = fun<number>(200);
具有许多类型参数的泛型 (Generics With Many Types Parameters)
If there are many parameters to a function, you can use other alphabets to denote the types. There is no restriction to use only T
.
如果函数有很多参数,则可以使用其他字母来表示类型。 没有限制只使用T
In other words, you can use your favorite alphabet. Let’s see how to work with many types.
换句话说,您可以使用自己喜欢的字母。 让我们看看如何使用多种类型。
function fun<T, U, V>(args1:T, args2: U, args3: V): V {
return args3;
}
Like with functions, we can use generics with classes
and interfaces
as well. Let’s explore them one by one.
与函数一样,我们也可以将泛型与classes
和interfaces
一起使用。 让我们一一探讨。
通用类 (Generic Classes)
Like generic functions, we can make our classes generic as well. We’ll pass the type
parameter, as usual, in angle (<>) brackets. Then use it across the class for defining methods and properties.
像通用函数一样,我们也可以使我们的类通用。 我们将像往常一样在尖括号(<>)中传递type
参数。 然后在整个类中使用它来定义方法和属性。
Let’s say we want to create a class that can take numbers
or string
input and creates an array out of it.
假设我们要创建一个可以接受numbers
或string
输入并从中创建数组的类。
class customArray<T> {
private arr: T[];
getItmes : T[] {
return this.arr;
}
addItem(item:T) {
this.arr.push(item);
}
removeItem(item: T) {
let index = this.arr.indexOf(item);
if(index > -1)
this.arr.splice(index, 1);
}
}
Now our generic class is ready. Let’s see how to use it for numbers
and string
data types.
现在我们的泛型类已经准备好了。 让我们看看如何将其用于numbers
和string
数据类型。
let numObj = new customArray<number>();
numObj.addItem(10);
let strObj = new customArray<string>();
strObj.addItem(“Robin”);
Note that we have used our class for both number
and string
types. You can play with the methods of this class.
请注意,我们已经在number
和string
类型中使用了我们的类。 您可以使用此类的方法。
通用约束 (Generic Constraints)
Up until this point, we are pretty much clear about TypeScript Generics, but there is one drawback I would like to bring your attention. But before that, let’s have a look at the below example.
到目前为止,我们对TypeScript泛型还很清楚,但是有一个缺点我想引起您的注意。 但是在此之前,让我们看一下下面的示例。
We’re going to write a function, which will return the length
of a function’s argument.
我们将要编写一个函数,该函数将返回函数参数的length
。
function getLength<T>(args: T) : number {
return args.length;
}
This function will work as long as the passing type as a length property. But what about other types, which don’t have a length
property. Guess what? You’re right, it will throw an exception!
只要传递类型作为length属性,此函数将起作用。 但是其他没有length
属性的类型呢? 你猜怎么了? 没错,它将引发异常!
Here’s the solution — putting generic constraints. Let’s see how to put the generic constraints to avoid such exceptions.
这是解决方案-放置通用约束。 让我们看看如何放置通用约束来避免此类异常。
First, we need an interface
and define a length
property.
首先,我们需要一个interface
并定义一个length
属性。
interface funcArgs {
length: number;
}
Now, change our above function and extend
it with this interface
to the constraint.
现在,更改上述函数,并使用此interface
extend
其extend
到约束。
function getLength<T extends funcArgs>(args:T) : number {
return args.length;
}
We’ve created a generic constraint using an interface
. Furthermore, we also extended our function getlength()
with this interface. It now needs length
as a required parameter.
我们使用interface
创建了通用约束。 此外,我们还通过该接口扩展了函数getlength()
。 现在需要length
作为必需参数。
In this case, accessing our function with an argument that doesn’t have a length parameter will show an exception message.
在这种情况下,使用没有长度参数的参数访问我们的函数将显示异常消息。
let result = getLength(3); // throw an exception
Here is the right way of calling the above function with length parameter.
这是使用length参数调用上述函数的正确方法。
let result = getLength({ length: 5, name: 'Hello'});
This is the right way of calling our function. This call has a length
property, and our function will work well. It will not show any error message.
这是调用函数的正确方法。 该调用具有length
属性,我们的函数将正常运行。 它不会显示任何错误消息。
翻译自: https://www.digitalocean.com/community/tutorials/typescript-generics-in-typescript
typescript泛型
下一篇: Android实现一个完美的倒计时功能