Ashun's 技術駅 Ashun's 技術駅
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • Vue
  • 现代web布局
  • React
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 技术资源
  • 第一阶段

    • HTML
  • 第二阶段

    • JavaScript
  • 第三阶段

    • Vue
  • 第四阶段

    • 实战项目
  • 每周测试

    • 每周
  • 其他

    • Vue引入UI框架
    • Web前端面试
    • Vue3-resource
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 福利资源
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Ashun

前端界的小学生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • Vue
  • 现代web布局
  • React
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 技术资源
  • 第一阶段

    • HTML
  • 第二阶段

    • JavaScript
  • 第三阶段

    • Vue
  • 第四阶段

    • 实战项目
  • 每周测试

    • 每周
  • 其他

    • Vue引入UI框架
    • Web前端面试
    • Vue3-resource
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 福利资源
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 01安装和配置文件
  • 02静态检查
  • 03类型推论
  • 04原始数据类型
  • 05any
  • 06unknown
  • 07never
  • 08数组
  • 09枚举类型
  • 10函数
  • 11类(class)
  • 12接口
  • 13联合类型&交叉类型
  • 14泛型
    • 1、定义泛型
    • 2、多个类型参数
    • 3、泛型变量
    • 4、泛型接口
    • 5、泛型类
    • 6、泛型约束
    • 7、泛型约束与索引类型
    • 8、多重类型约束
    • 9、约束为构造函数
  • 15类型断言
  • 16命名空间
  • 17声明文件
  • 18装饰器
  • 《TypeScript》
xugaoyi
2022-03-14
目录

14泛型

# 泛型

  • 泛型可以用来创建可重用的组件,一个组件可以支持多种类型的数据。

# 1、定义泛型

//这里的T可以传入任何类型数据,并返回相同的类型数据,相当于一个变量
function fn<T>(arg:T):T{
    return arg
}
1
2
3
4
//练习
function fn<T>(arg: T): T {
  return arg;
}

console.log(fn('hello 泛型'));
1
2
3
4
5
6

# 2、多个类型参数

//这里定义了两个不同的类型参数T、U,返回的值为U类型
function fn<T,U>(arg:T,arg2:U):U{
    return arg2
}
1
2
3
4
//练习
function fn<T, U>(arg: T, arg2: U): U {
  return arg2;
}

//console.log(fn(1, '2')); //2
console.log(fn('1', 2)); //2
1
2
3
4
5
6
7

# 3、泛型变量

  • 如果我们想传入一个数组,然后再函数里面打印数组的长度会显示报错,因为ts无法判断T类型有没有length属性
function fn<T>(arg:T){
    console.log(arg.length)//类型T不存在length属性
}
1
2
3
  • 这个时候我们可以把T类型作为数组的一部分
function fn<T>(arg:Array<T>){
    console.log(arg.length)//不报错
}
1
2
3
//练习

function fn<T>(arg: Array<T>): void {
  console.log(arg.length);
}
1
2
3
4
5

# 4、泛型接口

interface Fn<T>{
    (arg:T):T
}

const fn:Fn<number> = (arg)=>arg
//这里把number传入接口当成参数使用
1
2
3
4
5
6
//练习
interface Fn<T> {
  (arg: T): T;
}

let f: Fn<number> = function(arg) {
  return arg;
};
console.log(f(1));
1
2
3
4
5
6
7
8
9

# 5、泛型类

  • 泛型同样可以运用在类上。
class Arr{
    private arr:number[] = []//arr属性为一个空数组,类型是全部数字的数组

    public push(item:number){
        this.arr.push(item)
    }
}
1
2
3
4
5
6
7
  • 使用泛型。
class Arr<T>{
    private arr:T[] = []//arr数组里面的类型可以是任意的

    public push(item:T){
        this.arr.push(item)
    }
}
1
2
3
4
5
6
7
//练习
class Person<T> {
  constructor(name: T) {
    this.name = name;
  }
  name: T;
}

// let p = new.Person(123);
let p = new Person('泛型-字符串');
console.log(p.name);
1
2
3
4
5
6
7
8
9
10
11

# 6、泛型约束

  • 可以使用extends来约束泛型
function fn<T extends number | string>(arg:T){
    console.log(arg)
}

fn(1)//这里的参数只可以使用number或者是string类型
1
2
3
4
5
//练习

function fn<T extends number | string>(arg: T) {
  console.log(arg);
}
fn('字符串');
fn(123);
// fn(true) //这里就报错了
1
2
3
4
5
6
7
8

# 7、泛型约束与索引类型

  • 假如传入一个对象,再传入一个key,最后打印出这个对象的value值
function fn(obj:object,key:string){
    console.log(obj[key])//无法确定obj是否有key属性
}
1
2
3
  • 应该这样做
//T被约束为对象类型,U被约束为T的字段
function fn<T extends object,U extends keyof T>(obj:T,key:U){
    console.log(obj[key])//ok
}

let obj = {name:"小明",age:18}
fn(obj,"name")
1
2
3
4
5
6
7
//练习

// let obj{//代表【T】
//   name:""//代表【U】
// }

function fn<T extends object, U extends keyof T>(obj: T, key: U) {
  console.log(obj[key]);
}
1
2
3
4
5
6
7
8
9

# 8、多重类型约束

使用&和|对泛型进行约束

interface a{
    name:string
}

interface b{
    age:number
}

function fn<T extends a & b>(arg:T){
    console.log(arg)
}

fn({name:"小明",age:18})//必须同时符合a和b两种接口
interface a{
    name:string
}

interface b{
    age:number
}

function fn<T extends a | b>(arg:T){
    console.log(arg)
}

fn({name:"小明"})//只需要符合a或者b其中一个即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//练习

interface Person {
  name: string;
}

interface Student {
  age: number;
}

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

fn({
  name: '张三',
  age: 18
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 9、约束为构造函数

function fn<T>(type:T):T{
    return new type()//不可构造
}
1
2
3

正确做法

//写法1
function fn<T>(type:{new ():T}):T{
    return new type()
}

class Person{
    public name:string = "小明"
}

fn(Person)

//写法2
function fn<T,U>(arg:{new(U:string):T}):void{
    console.log(new arg("小红"))
}

class Person{
    constructor(name:string){
        this.name = name
    }
    name:string
}

fn(Person)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
编辑 (opens new window)
上次更新: 2023/08/06, 00:38:41
13联合类型&交叉类型
15类型断言

← 13联合类型&交叉类型 15类型断言→

最近更新
01
课件-react路由-V6
01-22
02
课件-国际化
01-22
03
课件-redux-toolkit
01-22
更多文章>
Theme by Vdoing | Copyright © 2019-2024 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式