TypeScript学习笔记(五) - 泛型

待我称王封你为后i 2022-05-27 01:58 311阅读 0赞

本篇将介绍在TypeScript如何使用泛型。

一、泛型方法

在TypeScript里,声明泛型方法有以下两种方式:

复制代码

  1. 1 function generics_func1<T>(arg: T): T {
  2. 2 return arg;
  3. 3 }
  4. 4 // 或者
  5. 5 let generics_func2: <T>(arg: T) => T = function (arg) {
  6. 6 return arg;
  7. 7 }

复制代码

调用方式也有两种:

  1. 1 generics_func1<string>('Hello world');
  2. 2 // 或者
  3. 3 generics_func2('Hello world');

第二种调用方式可以省略类型参数,因为编译器会根据传入参数来自动识别对应的类型。

在之前介绍的基本类型里,有一个any类型,表示不确定的类型。在具体使用时,可以代替任意类型,比如如下方法定义和实现:

复制代码

  1. 1 function any_func(arg: any): any {
  2. 2 return arg;
  3. 3 }
  4. 4
  5. 5 any_func(1);
  6. 6 any_func('Hello world!');
  7. 7 any_func(['1', '2']);

复制代码

看似与泛型方法类似,但是还是有区别的。比如如下例子:

复制代码

  1. 1 // 方法一:带有any参数的方法
  2. 2 function any_func(arg: any): any {
  3. 3 console.log(arg.length);
  4. 4 return arg;
  5. 5 }
  6. 6
  7. 7 // 方法二:Array泛型方法
  8. 8 function array_func<T>(arg: Array<T>): Array<T> {
  9. 9 console.log(arg.length);
  10. 10 return arg;
  11. 11 }

复制代码

在方法一的方法体里,打印了arg参数的length属性。因为any可以代替任意类型,所以该方法在传入参数不是数组或者带有length属性对象时,会抛出异常。而方法二定义了参数类型是Array的泛型类型,肯定会有length属性,所以不会抛出异常。

从上面这个例子可以看出,泛型类型相比较any类型来说,在某些情况下会带有类型本身的一些信息,而any类型则没有。

二、泛型类

以下是一个泛型类的定义和调用

复制代码

  1. 1 class Generics_Demo<T>{
  2. 2 value: T;
  3. 3 show(): T {
  4. 4 return this.value;
  5. 5 }
  6. 6 }
  7. 7
  8. 8 let gene_demo1 = new Generics_Demo<number>();
  9. 9 gene_demo1.value = 1;
  10. 10 console.log(gene_demo1.show()); // 调用方法
  11. 11
  12. 12 gene_demo1.show = function () { return gene_demo1.value + 1; } // 赋值新方法,返回值类型必须是number
  13. 13 console.log(gene_demo1.show());

复制代码

通过指定明确类型的泛型类的实例,对属性赋值时,必须满足实际类型的约束。

三、泛型类型

以下几个例子都是利用泛型类型定义变量或者方法参数的类型的示例

  1. 泛型接口

复制代码

  1. 1 interface Generics_interface {
  2. 2 <T>(arg: T): T;
  3. 3 }
  4. 4
  5. 5 function func_demo<T>(arg: T): T {
  6. 6 return arg;
  7. 7 }
  8. 8
  9. 9 let func1: Generics_interface = func_demo;

复制代码

上面的例子里,接口只有一个泛型方法成员。则用此接口类型定义的变量就是一个与成员类型一致的泛型方法。

将上面例子的泛型接口稍微改一下

复制代码

  1. 1 interface Generics_interface<T> {
  2. 2 (arg: T): T;
  3. 3 }
  4. 4
  5. 5 function func_demo<T>(arg: T): T {
  6. 6 return arg;
  7. 7 }
  8. 8
  9. 9 let func1: Generics_interface<number> = func_demo;
  10. 10 func1(123); // 正确类型的实际参数
  11. 11 func1('123'); // 错误类型的实际参数

复制代码

通过在接口上声明泛型,声明变量时明确指定泛型的具体类型,则赋值的方法将自动带上具体的类型约束。

  1. 泛型类型继承

复制代码

  1. 1 interface LengthInterface {
  2. 2 length: number;
  3. 3 }
  4. 4
  5. 5 function func_demo<T extends LengthInterface>(arg: T): T {
  6. 6 console.log(arg.length);
  7. 7 return arg;
  8. 8 }
  9. 9
  10. 10 func_demo({ a: 1, length: 2 }); // 含有length属性的对象
  11. 11 func_demo([1, 2]); // 数组类型

复制代码

上面的例子里,泛型类型继承自一个拥有length属性成员的接口,泛型类型将自动加上length属性的约束。调用时只有符合条件的对象才能正确赋值。

复制代码

  1. 1 function copy<T extends U, U>(source: U, target: T): T {
  2. 2 for (let prop in source) {
  3. 3 target[prop] = source[prop];
  4. 4 }
  5. 5
  6. 6 return target;
  7. 7 }
  8. 8
  9. 9 copy({ a: 1, b: 2 }, { a: 2, b: 3, c: 4 }); // 正确的实际参数
  10. 10 copy({ a: 1, b: 2 }, { q: 2, c: 4 }); // 错误的实际参数

复制代码

在上面的例子里,一个泛型类型继承自另外一个泛型类型。在方法调用时,就必须确保继承类型对应的参数对象属性完全包含被继承类型对应的参数对象。

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出作者名和原文连接,否则保留追究法律责任的权利。

发表评论

表情:
评论列表 (有 0 条评论,311人围观)

还没有评论,来说两句吧...

相关阅读

    相关 typescript基础——

    泛型定义 指在定义函数,接口或者类的时候,不预先指定具体的类型,在使用的时候再指定类型的一种特性; 使用 例如:定义一个函数,创建指定长度和值的数组 f

    相关 TypeScript

    > 泛型 generic,是泛指的类型。 > 在函数中使用泛型 / 泛型在函数中声明、使用 / // 可以定义多个泛型,指定多个参数的类型

    相关 typescript学习

    通俗理解:繁星就是解决 类 接口 方法的复用性,以及对不特定数据类型的支持 可以解决的问题:当一个函数在传入的参数是什么类型的时候,就要返回什么类型 T表示泛

    相关 Typescript-

    概念 TypeScript的泛型与其他面向对象的语言中的定义是相似的。泛型可以理解为在我们定义函数、接口或者类的时候,不预先指定其相关的类型,而是在使用的时候手动

    相关 TS学习笔记):

    泛型是指定一个表示类型的变量,用它来代替某个实际的类型用于编程,而后通过实际调用时传入或推导的类型来对其进行替换,以达到一段使用泛型程序可以实际适应不同类型的目的。为了实现泛型