TypeScript之泛型

为什么要用泛型

  1. 定义时就限制类型
    function echo(arg:number):number{
        return arg
    }
    
    只能传入number类型,无法传入string等类型
    const result = echo(2)
    
  2. 采用any
    function echo(arg:any):any{
        return any
    }
    
    是可以支持传入任何类型,可传入与返回的类型可以不一致。比如我们输入个number类型,我们只知道任何类型的值都有可能返回

泛型

定义

在定义函数,接口或类时,不预先指定具体类型,而是在使用的时候动态填入确定类型值

使用

在函数名后加上,其中T可以换成任意字符。T帮助捕获传入的类型(比如 number),之后我们就可以在参数以及返回值里用这个类型T,就达到了传入类型与返回类型一致的效果
示例1:

function echo<T>(arg:T):T{
    return any
}
const result = echo(123)

示例2

function swap<T,U>(tuple:[T,U]):[U,T]{
  return [tuple[1],tuple[0]]
}
const s = swap(["23",23])

约束泛型

为什么会有约束泛型

function echoWithLen<T>(arg:T):T{
    console.info(arg.length) // Error: T doesn't have .length
    return arg;
}

报错的原因是:T代表任意类型,所以使用这个函数的人可能传入boolean类型,而boolean类型是没有length属性的
改成:

function echoWithArr<T>(arg:T[]):T[]{
    console.info(arg.length) 
    return arg;
}
const arr = echoWithArr([1,2,3])
const arr2 = echoWithArr([1,2,"3"]) //T变成了number|string
// const arr3 = echoWithArr('str') //string实际上也有length属性,却会报错,所以这种定义方式有问题

采用interface extends

interface IWithLength {
  length:number
}
function echoWithArr2<T extends IWithLength>(arg:T):T {
  return arg
}
const arrWith = echoWithArr2([1,2,3])
const arrWith2 = echoWithArr2('str')
// const arrWith3 = echoWithArr2(23)  //不可以,因为number没有length属性

泛型在对象上的使用

interface KeyPair<T,U> {
  key:T,
  value:U
}
let kp1:KeyPair<number,string> = {key:23,value:"23"}
let kp2:KeyPair<string,number> = {key:"23",value:23}

Array<类型>就是这种用法

let n:number[] = [2,3,4]
let n2:Array<number> = [2,3,4]

泛型在函数上的使用

interface IPlus2<T> {
  (a:T,b:T):T
}
function plus2(a:number,b:number) :number {
  return a+b;
}
function connect(a:string,b:string) :string {
  return a+b;
}
const p2:IPlus2<number> = plus2
const c2:IPlus2<string> = connect

泛型在类上的使用

不使用typescript

class Queue {
  private data = []
  push(item) {
    return this.data.push(item)
  }
  pop(){
    return this.data.shift()
  }
}
const queue = new Queue()
queue.push(1)
queue.push("str")
console.info(queue.pop().toFixed())
// console.info(queue.pop().toFixed()) //运行时才会报错

使用typescript基本类型校验

class Queue {
  private data = []
  push(item:number) {
    return this.data.push(item)
  }
  pop():number{
    return this.data.shift()
  }
}
const queue = new Queue()
queue.push(1)
// queue.push("str") //会报错,起到了限制作用
console.info(queue.pop().toFixed())

使用泛型类

上面的起到了只允许传入number类型,但如果要弄个允许加入字符串,就得重新定义个类,这不合理

class Queue<T> { 
  private data = []
  push(item:T) {
    return this.data.push(item)
  }
  pop():T{
    return this.data.shift()
  }
}
const queue = new Queue<number>()
queue.push(3)
console.info(queue.pop().toFixed()) //3
const queueStr = new Queue<string>()
queueStr.push("3")
console.info(queueStr.pop().indexOf("3")) //0
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
泛在TypeScript中是一种特性,它允许我们在定义函数、接口或类时不预先指定具体的类型,而是在使用时手动指定类型。它可以帮助我们在编写可重用的代码时增加类型的安全性和灵活性。 在TypeScript中,使用尖括号(< >)来表示泛型,并在类名、函数名或接口名后面使用泛型变量来表示类型参数。例如,我们可以定义一个泛型函数来实现数组元素的反转: ```typescript function reverse<T>(array: T[]): T[] { return array.reverse(); } const numbers = [1, 2, 3, 4, 5]; const reversedNumbers = reverse(numbers); // [5, 4, 3, 2, 1] const names = ["Alice", "Bob", "Charlie"]; const reversedNames = reverse(names); // ["Charlie", "Bob", "Alice"] ``` 在上面的例子中,泛型变量`T`表示类型参数,它可以在函数体内部和函数的参数类型中使用。 除了函数,我们还可以使用泛型来定义类和接口。例如,我们可以创建一个泛型类`Box`来存储不同类型的值: ```typescript class Box<T> { private value: T; constructor(value: T) { this.value = value; } getValue(): T { return this.value; } } const numberBox = new Box<number>(42); console.log(numberBox.getValue()); // 42 const stringBox = new Box<string>("Hello"); console.log(stringBox.getValue()); // "Hello" ``` 上面的例子中,泛型变量`T`可以在类的成员变量类型、构造函数参数类型和方法返回值类型中使用。 总结来说,TypeScript泛型提供了一种灵活的方式来增加代码的可重用性和类型安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值