泛型 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中的泛型应用于classesinterfacesfunctions

什么是泛型? (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.

注意,这里我们对numberstring类型重复相同的功能。 在这种情况下,有一种使其通用的方法–使用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.

在交换numberstring类型以键入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.

结果,它现在是类型安全的。 让我们看看如何对stringnumber类型使用相同的功能。

// 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.

像函数一样,我们也可以将泛型与classesinterfaces一起使用。 让我们一一探讨。

通用类 (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.

假设我们要创建一个可以接受numbersstring输入并从中创建数组的类。

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.

现在我们的泛型类已经准备好了。 让我们看看如何将其用于numbersstring数据类型。

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.

请注意,我们已经在numberstring类型中使用了我们的类。 您可以使用此类的方法。

通用约束 (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 extendextend到约束。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值