【TS】泛型 Generics

泛型Generics,是指在定义函数Function、接口Interface 或类 Class 时不预先指定具体的类型,而是在使用的时候再指定类型的一种特征。

// 函数名后的 <> 内传入泛型参数,在使用时指定类型
function echo<T>(arg: T): T {
    return arg
}

const str: string = 'str'
const result = echo(str) //类型推论会推论出参数的类型

泛型可以看作是类型变量,它是一种特殊的变量,只用于表示类型而不是值。在使用时把类型像参数一样传入。

function swap<T, U>(tuple: [T, U]): [U, T] {
    return [tuple[1], tuple[0]]
}

const result2 = swap(['string', 123])
results[1].fixed() // 可以调用Number方法

约束泛型-函数(在函数的参数和返回值中使用泛型)

有时候想操作某类型的一组值,并且我们知道这组值具有什么样的属性。 在 下面例子中,我们想访问arglength属性,但是编译器并不能证明每种类型都有length属性,所以就报错了。

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

相比于操作any所有类型,我们想要限制函数去处理任意带有.length属性的所有类型。 只要传入的类型有这个属性,我们就允许,就是说至少包含这一属性。 为此,我们需要列出对于T的约束要求。

为此,我们定义一个接口来描述约束条件。 创建一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束:

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // Now we know it has a .length property, so no more error
    return arg;
}

// 现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
loggingIdentity(3);  // Error, number doesn't have a .length property

// 我们需要传入符合约束类型的值,必须包含必须的属性:
loggingIdentity({length: 10, value: 3});
loggingIdentity([1, 2, 3]);
loggingIdentity('string');

约束泛型-类 Class

// 队列类-先进先出
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.log(queue.pup().toFixed()) // 1
//  string 类型并无toFixed 方法 
console.log(queue.pop().toFixed()) // Error:...toFixed is not a function



/*-- 解决以上问题需要为该类添加泛型约束 --*/ 
class Queue<T> {
    private data = []
    push(item: T) {
        return this.data.push(item)
    }
    pop(): T {
        return this.data.shift()
    }
}

// 实例化类-添加实例类型 number
const queue = new Queue<number>()
queue.push(1)
// queue.push('str') // 已不符合约定的类型
console.log(queue.pop().toFixed()) // 1
//  string 类型并无toFixed 方法 
console.log(queue.pop().toFixed()) // Error:...toFixed is not a function

// 实例化类-添加实例类型 string
const queue = new Queue<string>()
queue.push(1)
console.log(queue.pop().length) // 1

约束泛型- Interface

interface KeyPair<T, U> {
    key: T;
    value: U;
}
let kp1: KeyPair<number, string> = { key: 123, value: 'str'}
let kp2: KeyPair<string, number> = { key: 'str', value: 123}

let arr: number[] = [1, 2, 3]
let arrTwo: Array<number> = [1, 2, 3]

在interface 函数中使用泛型

interface IPlus<T> {
    (a: T, b: T): T
}
function plus(a: number, b: number): number {
    return a + b
}
function connect(a: string, b: string): string {
    return a + b
}
const a: IPlus<number> = plus()
const b: IPlus<string> = connect()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TypeScript泛型可以让我们编写可重用的代码组件,这些组件可以支持多种类型。泛型TypeScript 的一个强大特性,它可以在函数、类、接口中使用。 泛型的基本语法是在函数名或类名后加上 "<T>"(T可以是任何标识符),这个T表示类型变量,它可以代表任意类型。例如: ```typescript function identity<T>(arg: T): T { return arg; } let output = identity<string>("hello world"); console.log(output); // 输出 hello world ``` 在上面的例子中,我们定义了一个名为 identity 的函数,它接收一个参数 arg,并返回该参数。在函数名后面加上了 "<T>",这样我们就可以在函数中使用类型变量 T,代表任意类型。 调用 identity 函数时,我们可以明确指定 T 的类型,例如:identity<string>("hello world"),这表示 T 的类型是 string。也可以不指定 T 的类型,TypeScript 会根据传入的参数自动推断出 T 的类型,例如:identity("hello world"),TypeScript 会自动将 T 推断为 string。 泛型还可以用于类和接口中,例如: ```typescript interface GenericIdentityFn { <T>(arg: T): T; } class Identity<T> { private value: T; constructor(value: T) { this.value = value; } getValue(): T { return this.value; } } let myIdentityFn: GenericIdentityFn = identity; let myIdentity = new Identity<string>("hello"); console.log(myIdentity.getValue()); // 输出 hello ``` 在上面的例子中,我们定义了一个名为 GenericIdentityFn 的接口,它定义了一个泛型函数。我们还定义了一个名为 Identity 的类,该类接收一个类型参数 T,并存储一个类型为 T 的值。 通过泛型,我们可以编写可重用的代码组件,它可以支持多种类型,提高代码的复用性和灵活性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值