泛型 typescript



TypeScript, a “superset of JS”, makes it easier to build maintainable, comprehensible, and scalable apps thanks to the power of type-checking.

TypeScript是JS的“超集”,得益于类型检查的强大功能,它使构建可维护,可理解和可扩展的应用程序变得更加容易。

Generics play an important role in TypeScript as it allows us to write reusable code that accepts both values and types as arguments.

泛型在TypeScript中起着重要的作用,因为它允许我们编写将值和类型都作为参数接受的可重用代码。

(Generics in functions)

Generics help us in making our code more reusable. Let’s try to understand what are generics and why do we need them with the help of the below example:

泛型帮助我们使代码更可重用。 让我们尝试通过以下示例了解什么是泛型以及为什么需要它们:



Please note in the above snippet, we have three functions doing pretty much the same thing. It’s duplicated code and screams for making it reusable.

请注意,在上面的代码段中,我们有三个功能几乎可以完成相同的事情。 它是重复的代码,并为使其可重复使用而尖叫。

One thing we could do is to put a type of any so that String, Number, and Person type of values can call be used as arguments in the same function. Unfortunately, that introduces more problems then it solves (in general, if you’re planning to use the any type very often, it’s maybe best to keep it pure JS).

我们可以做的一件事就是放置any类型,以便可以在同一函数中将String,Number和Person类型的值用作参数。 不幸的是,这带来了更多的问题,而后又解决了(通常,如果您打算经常使用any类型,最好将其保留为纯JS)。

Solving the “reusability problem” using Generics — An example:

使用泛型解决“可重用性问题” —示例:



The converToValueArray function receives a value of the chosen type <T> and returns an array of that type: Array<T>. So, for example, if the value is of String type then the return type is Array<String>

converToValueArray函数接收所选类型<T>的值,并返回该类型的数组: Array<T> 。 因此,例如,如果该值为String类型,则返回类型为Array<String>

Let’s see how TypeScript shows an error when we define our generic type.

让我们看看定义通用类型时TypeScript如何显示错误。




android 泛型T解析 泛型js_python

Please note, in line 18, after using the Generics, if we want to access age, it shows the correct error, which is what we want to get early feedback on any kind of error.

请注意,在第18行中,使用了泛型之后,如果我们要访问age,它将显示正确的错误,这是我们希望早日获得有关任何错误的反馈的信息。

(Inferred type)

Let’s define a function that takes a generic type.

让我们定义一个采用通用类型的函数。

function convertToArray<T>(args: T): Array<T> {
  return [args];
}

We can call the function in two ways

我们可以通过两种方式调用该函数

convertToArray("someString");convertToArray<String>("someString");

As we can see, if the type is not passed in <> then the type is automatically inferred. Type inference keeps the code shorter, but in complex definitions, we might need to explicitly pass the type.

如我们所见,如果未在<>传递类型,则将自动推断类型。 类型推断使代码更短,但是在复杂的定义中,我们可能需要显式传递类型。

(More than one generic type)

Just like function arguments we can pass more than one type, which is irrespective of the number of function arguments. E.g

就像函数参数一样,我们可以传递不止一种类型,而与函数参数的数量无关。 例如

function doStuff<T, U>(name: T): T {
  // ...some process
  return name;
}

The above function can be called as follows:

上面的函数可以如下调用:

doStuff<String, Number>("someString");

(Generic classes)

Many times we would require to create a generic class, e.g Base abstract classes. Where we can pass the types while creating instances of classes.

很多时候,我们需要创建一个通用类,例如基础抽象类。 创建类实例时可以在其中传递类型的地方。


As we can see, in line 6 we have created a base local database class, which we can use to create an instance for one specific table and perform operations on the database instance. Let’s write a contact class which extends this base class so that it can inherit some properties from parent.

如我们所见,在第6行中,我们创建了一个基本的本地数据库类,我们可以使用该类为一个特定的表创建一个实例,并对数据库实例执行操作。 让我们编写一个扩展此基类的contact类,以便它可以从父类继承一些属性。


  • Line 14, when we extend the generic class, we have to pass two types, in this database. In our case ContactTable and ContactModel.
  • Line 17: The ContactLocalDatabase will get the functions from the parent class, and has to override the getFormattedData, as this is defined as an abstract function in the parent base class.
    第17行: ContactLocalDatabase将从父类获取函数,并且必须重写getFormattedData ,因为在父基类中将其定义为抽象函数。
  • Line 17: This is now the function that has a generic type, which we discussed in the first section.

Let’s create an instance of the ContactLocalDataBase to see class generics in action.

让我们创建一个ContactLocalDataBase的实例,以查看实际的类泛型。


  • Line 1: as we have defined the types of ContactLocalDatabase class when using new keyword, the types need not be passed to the base class.
    第1行:由于我们在使用new关键字时定义了ContactLocalDatabase类的类型,因此无需将这些类型传递给基类。
  • Line 3, 11, 13: we can notice that these functions are from the abstract class. These behave as per the generic class definitions.

(Generic constraints)

So far, it is quite clear that generics are a way of writing code such that our code can support more than one type and the type can be passed as a parameter.

到目前为止,很明显,泛型是一种编写代码的方式,这样我们的代码可以支持多个类型,并且该类型可以作为参数传递。

Given this knowledge, the passed type can be any predefined type or complex user-defined type.

有了这些知识,传递的类型可以是任何预定义类型或复杂的用户定义类型。

Sometimes if we want to access any function from the generic typed variable, it will throw an error.

有时,如果我们想从通用类型变量访问任何函数,它将抛出错误。


android 泛型T解析 泛型js_泛型_02

  • Line 6: This is totally valid error, as data has a generic type and it can be either String, Number, Float, or any other type and the passed data may or may not have length.

Hence we can add some constraints to any generics, where TS will make sure, only those values can be passed to function or class, which fulfills the constraint. Let’s add some constraints to our generic function definition.

因此,我们可以向任何泛型添加一些约束,TS将确保只有那些值可以传递给满足约束的函数或类。 让我们在通用函数定义中添加一些约束。


android 泛型T解析 泛型js_python_03

  • Line 4: we have extended the type T to have a length property
    第4行:我们将类型T扩展为具有长度属性
  • Line 5: the error disappeared, which said property length does not exist on type ‘T’
  • Line 10: when we call the function with a number, it throws error explaining it doesn’t fulfill the constraint
  • Line 12 and 13: when we pass valid data like String or Array, TS doesn’t throw an error.

That’s all for this post, I hope you learned the basics of Generics and the value it generates.

这就是这篇文章的全部内容,希望您学习了泛型的基础知识及其所产生的价值。

If you don’t know the basics of Generics, it looks very complicated.

如果您不了解泛型的基础知识,则它看起来非常复杂。

I hope your time was worth reading this post.

希望您的时间值得阅读这篇文章。


翻译自: https://levelup.gitconnected.com/understanding-generics-in-typescript-5c0828e2cfd5

泛型 typescript