Typescript - 泛型介绍与使用方法教程

介绍

泛型:generics,参数化类型,全称为 泛型参数,我们接下来都简称为泛型 。

学过面向对象语言的小伙伴都知道继承。但是在这里我要说的是:继承不是某一门语言的特性,是某一类语言的特性。哪一类呢?答案是面向对象语言。好了,问题又来了,面向对象语言为什么要实现继承的特征呢?因为继承背后的思想是代码重用/复用/共享,编写的代码可以被许多派生类型的对象所重用。

因为我们要复用代码,所以有了继承。

有时候我们嫌代码的力度太小,想要复用文件,怎么办呢?import 关键字应运而生。在Java里面,import 运行后被编译器替换为包的路径限定名。语法 import 包名 帮助我们实现了文件的复用。

在JavaScript里面, import 文件名 运行后帮助我们在作用域链上方建立了一个 module 作用域。import 帮助我们实现了文件的复用。

小示例

写一个函数,这个函数会返回任何传入的值。

eg:不用泛型的话,这个函数可能是下面这样:

function identity(arg: number): number {
    return arg;
}

如果我们要编写框架,就要考虑到各种返回值的情况,于是可能就会有这样的代码:

type idBoolean = (arg: boolean) => boolean;
type idNumber = (arg: number) => number;
type idString = (arg: string) => string;

很明显,我们的这些代码逻辑是相同的,但是由于需要,我们不得不写 n 遍这样的逻辑。

有些小伙伴可能会说,我们可以使用any类型来定义函数:

function identity(arg: any): any {
    return arg;
}

使用any类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。

所以为了解决算法的复用,我们引入了泛型的概念。如下所示:

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

我们给identity添加了类型变量T。 T帮助我们捕获用户传入的类型(比如:number),之后我们就可以使用这个类型。

接下来我们就可以通过这样的语法调用 identity 函数。

identity<string>('hello');

泛型就是创建类型变量用以接受任意类型。

泛型是什么?

普通函数要求我们对 值 编程,泛型则要求我们对 类型 编程。

啊?天呐!类型还可以编程?当初笔者也比较迷惑,类型怎样编程,后来随着对TS的深入理解,逐渐清晰了所谓的类型编程和值编程。

类型编程

接下来带你体验一下所谓的类型编程。

我们在 TypeScript 中有这样两个操作符 ‘|’ 和 ‘&’。

  • ‘|’:取并集运算符。
  • ‘&’:取交集运算符。

我们先来看看集合的概念。

文氏图

文氏图用于展示在不同的事物群组(集合)之间的数学或逻辑联系,尤其适合用来表示集合(或)类之间的 “大致关系”,它也常常被用来帮助推导(或理解推导过程)关于集合运算(或类运算)的一些规律。

在文氏图法中,如果有论域,则以一个矩形框(的内部区域)表示论域;各个集合(或类)就以圆/椭圆(的内部区域)来表示。两个圆/椭圆相交,其相交部分表示两个集合(或类)的公共元素,两个圆/椭圆不相交(相离或相切,而实际上在文氏图中相切是没有什么意义的,因为文氏图是以图形的内部区域来表示的)则说明这两个集合(或类)没有公共元素。

比如黄色的圆圈(集合 A)可以表示两足的所有动物。蓝色的圆圈(集合 B)可以表示会飞的所有动物。黄色和蓝色的圆圈交叠的区域(叫做交集)包含会飞且两足的所有动物 —— 比如鹦鹉。 (把每个单独的动物类型想像为在这个图中的某个点)。

Typescript - 泛型介绍与使用方法教程_第1张图片

在TypeScript中,我们的类型就是取自集合的思想。例如: string 类型是所有字符串的集合, number 是所有数字的集合。在 TS 中不仅有这些已经定义好的类型,还有可以提供我们自定义类型的关键字。例如: interface 。我们使用联合类型(A|B)表示集合中的元素属于 A 或者属于 B 。使用交叉类型(A&B)表示集合中的元素既属于 A 又属于 B 。

如果 A = {name: string} , B = {age: number},那么
属于 A 或者属于 B的元素(A|B)为仅仅包含name或仅仅包含age或包含name和age的对象,既属于 A 又属于 B的元素(A&B)为包含name和age的对象。

示例1:

在 TypeScript 中编程要注意将文件的

interface cat = {name: string, purrs: boolean};
interface dog = {name: string, barks: boolean};
interface catAndDog = cat & dog;
interface catOrDog = cat | dog;
let a: catOrDog = {name: 'jack',purrs: true,barks: boolean};
a = {name: 'jack', purrs: true};
a = {name: 'jack', barks: true};
let b: catAndDog = {name: 'tom',purrs: true,barks: boolean}

示例2:

假设我们定义了一个person shape:

interface Person {
    name: string,
    age: number,
    phone: string
}

有一个需求是填写表单并统计,其中 name age 和 phone 是k可选的,但是 age 是可选的。我们可以再造一个接口

interface Person {
    name?: string,
    age?: number,
    phone?: string
}

好了,我们的需求解决了,啊哈。

不过TypeScript为我们提供了一种更好的方式----Partial。我们还可以通过这种方式 Partial 实现上面的需求。

嗯????Partial帮助我们完成了什么工作呢?怎么就这么突然就帮我们将 Person 的必选项转化为可选项了呢?我们来猜想一下他的实现步骤~

// js伪代码
functon Partial(Type){
    // 遍历Type
    for(k in Type){
        // 将Type中的每个元素转化为可选的
        Type[k] = Optional(k);
    }
    return Type;
}
// 可以看成是上面的函数定义,可以接受任意类型。由于是这里的 “Type” 形参,因此理论上你叫什么名字都是无所谓的,就好像函数定义的形参一样。
type Partial<Type> = { do something }
// 可以看成是上面的函数调用,调用的时候传入了具体的类型 Person
type PartialedPerson = Partial<Person>

接下来看下函数调用和类型调用写法对比。





ts 泛型的作用,TS中的泛型TS-泛型的基本用法TS 一些工具泛型的使用及其实现ts泛型详细教程TS中的泛型精简(快速掌握)TS学习之泛型TS 泛型如何使用TS之泛型的使用TS-泛型的基本使用TS-泛型的基本用法ts中泛型的使用ts泛型方法的定义和使用,ts泛型怎么写【TypeScript】TS泛型讲解及其使用在TypeScript 中使用泛型的方法Typescript中的泛型的作用及使用场景 ts泛型接口的使用TS 如何在 interface 内使用泛型Typescript - 泛型介绍与使用方法教程

你可能感兴趣的:(javascript,typescript,ts泛型教程,ts泛型使用方法,最好的教程,typescript,泛型应用)