美文网首页TypeScriptTypeScript
TS学习笔记(五):泛型

TS学习笔记(五):泛型

作者: 半掩时光 | 来源:发表于2019-05-11 23:33 被阅读0次

泛型是指定一个表示类型的变量,用它来代替某个实际的类型用于编程,而后通过实际调用时传入或推导的类型来对其进行替换,以达到一段使用泛型程序可以实际适应不同类型的目的。为了实现泛型所要达到的目的,我们也可采用指定类型为 any 或者为每一种可能的类型都写一个方法(重载),但这严重违反抽象和复用代码的原则。所以在考虑可重用组件的时候,我们应该使用泛型。

泛型其实是 C# 和 Java 这种强类型语言中的一个特性,TypeScript 把这一特性引进到了弱类型语言 JavaScript 中,对于没接触过强类型语言的前端 coder,理解这个概念可能有点吃力,如果看不太懂,可以先去了解一下 Java 中的泛型,下面进入正题。

初识泛型

定义泛型:我们把要传入函数的参数类型设为一个类型变量 T ,它能够帮助我们捕获用户传入的类型,之后出现 T 的地方,都会被替换成用户传入的类型。

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

function getFirst<T>(arr: T[]): T {
  return arr[0];
}

console.log(identity(10)); // 10
console.log(identity('TS')); // TS
console.log(getFirst([1, 2, 3, 4])); // 1
console.log(getFirst(['a', 'b', 'c'])); // a

使用泛型:有两种使用泛型的方式,第一种是传入所有的参数,包括类型参数;第二种是不传类型参数,因为 TypeScript 的编译器会利用类型推论来确定参数的类型,推荐使用第二种。

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

function getFirst<T>(arr: T[]): T {
  return arr[0];
}

// 使用一:传入所有参数
console.log(identity<number>(10)); // 10
console.log(identity<string>('TS')); // TS
console.log(getFirst<number>([1, 2, 3, 4])); // 1
console.log(getFirst<string>(['a', 'b', 'c'])); // a
// 使用二:不传参数类型
console.log(identity(10)); // 10
console.log(identity('TS')); // TS
console.log(getFirst([1, 2, 3, 4])); // 1
console.log(getFirst(['a', 'b', 'c'])); // a

泛型类型

一个泛型函数的类型如下:

<泛型变量名称>(参数1: 泛型变量, 参数2: 泛型变量, ...参数n: 泛型变量) => 泛型变量

可以以对象字面量的形式来定义泛型函数(这更像是接口),如:

let foo: { <T>(arg: T): void };
foo = function <T>(arg: T): void {
  console.log(arg);
}
foo(13); // 13

将上面的例子中的 { <T>(arg: T): void }改为接口,则有:

interface IGeneric {
  <T>(arg: T): void
}
let foo: IGeneric = function <T>(arg: T): void {
  console.log(arg)
}
foo(13); // 13

最后,接口中也可以使用泛型,这样子就锁定了代码里可以使用的类型,如:

interface IGeneric<T> {
  (arg: T): void
}

function fn<T>(arg: T): void {
  console.log(arg);
}

let myFn: IGeneric<number> = fn;
myFn(13); //13

泛型类

除了泛型接口,我们还可以创建泛型类(但是无法创建泛型枚举、泛型命名空间),泛型类使用 <> 包围泛型类型变量,如:

class Person<T> {
  love: T;
  say: (arg: T) => T;
}

let me = new Person<string>();
me.love = 'TS';
// me.love = 520; // ERROR
me.say = function(love: string){
  return `my love is ${love}`;
}

console.log(me.say('TS')); // my love is TS

注意:类有两部分,分为静态部分和实例部分,泛型类的类型指的是实例部分的类型,静态属性不能使用该泛型类型。

泛型约束

泛型可以通过 extends 一个接口来实现泛型约束,写法如:<泛型变量 extends 接口> ,例子:

interface IArray {
  length: number
}

function logIndex<T extends IArray>(arg: T): void {
  for (let i = 0; i < arg.length; ++i) {
    console.log(i)
  }
}

let arr = [1, 2, 3]
// logIndex<number>(arr) // 报错
logIndex<number[]>(arr) // 允许
logIndex(arr) // 自动类型推导,允许

可以在泛型里使用类类型,如使用泛型创建工厂函数,需要引用构造函数的类类型,有:

function create<T>(c: { new(): T }): T {
  return new c()
}

相关文章

  • TS学习笔记(五):泛型

    泛型是指定一个表示类型的变量,用它来代替某个实际的类型用于编程,而后通过实际调用时传入或推导的类型来对其进行替换,...

  • 【第7篇】TypeScript泛型的案例代码详解

    1、最简单泛型例子 Ts代码 Js文件 2、泛型类型与接口 Ts代码一 Ts编译js代码一 Ts代码二 Ts编译j...

  • TypeScript基础入门 - 泛型 - 泛型类

    转载 TypeScript基础入门 - 泛型 - 泛型类 项目实践仓库 为了保证后面的学习演示需要安装下ts-no...

  • TypeScript基础入门 - 泛型 - 泛型约束

    转载 TypeScript基础入门 - 泛型 - 泛型约束 项目实践仓库 为了保证后面的学习演示需要安装下ts-n...

  • TypeScript基础入门 - 泛型 - 使用泛型变量

    转载 TypeScript基础入门 - 泛型 - 使用泛型变量 项目实践仓库 为了保证后面的学习演示需要安装下ts...

  • TypeScript基础入门 - 泛型 - 泛型类型

    转载 TypeScript基础入门 - 泛型 - 泛型类型 项目实践仓库 为了保证后面的学习演示需要安装下ts-n...

  • TS笔记之 泛型

    泛型 介绍 软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据...

  • TS 笔记九 泛型

    参考C# 泛型 泛型与非泛型集合[https://www.jianshu.com/p/e45e7573f928] ...

  • TS 泛型

    定义 泛型就是用一个东西表示广泛的类型。 接口 泛型约束 就是给泛型添加一些约束。

  • TS: 泛型

    学 Java 的时候总会提到泛型,现在 TS 也有了,他们的用法都差不太多。泛型可以理解为广泛的类型。 为什么要用...

网友评论

    本文标题:TS学习笔记(五):泛型

    本文链接:https://www.haomeiwen.com/subject/voqqaqtx.html