TypeScript(九)泛型基础

简介: TypeScript(九)泛型基础

前言

本文收录于TypeScript知识总结系列文章,欢迎指正!

代码复用是开发人员老生常谈的问题了,我们通过定义变量,使用函数或类减少代码重复编写。

在TS中我们可以把编写一个类型看成是新建一个函数,参数便是今天的主角:泛型,通过传入不同的参数(类型)控制类型的走向,达到类型复用的目的

定义

泛型类型是指一种不确定的类型,它允许开发者在定义函数、类、接口时不指定具体的类型,而是使用一个占位符类型,等到函数、类、接口被调用时再动态地传入具体类型,以便让它们适用于多种不同类型的数据。

使用泛型可以使代码更加通用、可复用、可扩展,提高代码的质量和可维护性。

基本用法

泛型使用尖括号<T>表示,其中T可以被任意字母替换,它代表一种类型,在使用时需要将其替换为具体的类型。

还记得之前数组的泛型写法吗?

const arr: Array<string> = ["a", "b"]

我们使用尖括号来标注泛型的实际类型

在JS中我们都会定义函数,每个函数的行为走向或许由参数决定,举个例子

type IObj = {
    name?: string
}
interface ISetKey {
    (obj: IObj, key: string): IObj
}
const setName: ISetKey = function (obj: IObj, name: string): IObj {
    if (!!!obj.name) obj.name = name
    return obj
}
const obj: IObj = setName({}, "张三")

上面这段代码,我实现了一个给对象设置值的函数,乍一看似乎没啥毛病,但是如果我给上述的代码增加一个age操作

type IObj1 = {
    age?: number
}
const setAge: ISetKey = function (obj: IObj1, age: number): IObj1 {
    if (!!!obj.age) obj.age = age
    return obj
}
const obj1: IObj1 = setAge({}, 20)

ISetKey这个接口几乎是要重新写了,它的结构也要随着改变,变成

interface ISetKey1 {
    (obj: IObj1, key: number): IObj1
}

通过这个小例子我们可以看到,如果我们在ISetKey中使用两个变量O和K来代表参数的两个类型,那么我们就可以使接口或者类型达到复用的效果

interface ISetKey<O, K> {
    (obj: O, key: K): O
}

使用效果:

const setName: ISetKey<IObj, string>
 
const setAge: ISetKey<IObj1, number>

掌握了上述的代码,就说明我们对泛型有了一个认识和入门

泛型命名约定

泛型的定义使用T或U之类的是为了表达特定的含义或约定,目的是增强代码的可读性,当然这些是对命名的俗成,泛型的写法是自由选择的,没有硬性要求或规定;下面我会列举一些常见的写法供参考

常见的T表示类型(type),U是未知(unknown),N表示数字(number),V是值(value)

此外还有K键名,A数组,R函数返回值,M映射等等

泛型&类型别名

既然泛型可以代表一种类型,我们可以将泛型类型参数作为类型别名的一部分与类型别名一起使用

type Animal<T, N> = {
    name: T
    age: N
}
 
const animal: Animal<string, number> = {
    name: "阿黄",
    age: 10
}

上面代码中我们实现了对Animal类型的动态描述,T表示name的类型,N表示age的类型

泛型&接口

接口中使用泛型和类型别名很相似,同样是在定义的接口名后面声明参数,在类型使用时动态传入具体类型,下面是数组及部分属性和函数的写法

interface MyArray<T> {
    [num: number]: T
    length: number
    push: (...item: T[]) => number
    forEach: (cb: (item: T, i: number, arr: MyArray<T>) => void) => void
}
const list: MyArray<string> = ["a", "b"]
console.log(list.push("c"));
list.forEach(console.log)
console.log(list);
/*
输出:
3
a 0 [ 'a', 'b', 'c' ]
b 1 [ 'a', 'b', 'c' ]
c 2 [ 'a', 'b', 'c' ]
[ 'a', 'b', 'c' ]
*/ 

泛型&函数

泛型函数的写法和上面类似

// 函数声明
function getValue<T>(val: T): T {
    return val;
}
// 函数表达式
const getValue1 = function <T>(val: T): T {
    return val;
}
// 箭头函数
const getValue2 = <T>(val: T): T => {
    return val
}
 
getValue<string>("abc")
getValue1<number>(123)
getValue2<boolean>(true)

泛型&类

使用泛型来定义类,可以使类中的成员方法和属性更加灵活和通用,泛型类的使用方式与泛型接口类似,在类名后添加一个<T>来表示泛型类

interface IDog {
    name?: string
    likeMeat: boolean
}
interface ICat {
    name?: string
    likeFish: boolean
}
class Animal<Type>{
    constructor(public animalType: Type) { }
}
const dog: IDog = {
    name: "阿黄",
    likeMeat: true
}
const cat: ICat = {
    name: "小橘",
    likeFish: true
}
new Animal<IDog>(dog)
new Animal<ICat>(cat)

上述代码中,我们使用Type表示传入Animal类的动物类型,当传入IDog时,类的实例会限制其参数传入IDog的实现;ICat同理。

泛型默认值

在之前的文章中,我们了解过参数的可选性,函数的参数可以指定默认值。泛型的参数亦是如此,在不传递泛型类型参数时使用默认值可以替代参数。使用上面类型别名的例子

type Animal<T = string, N = number> = {
    name: T
    age: N
}
 
const animal: Animal = {
    name: "阿黄",
    age: 10
}

结语

本篇文章讲述的是泛型基础,我分别从泛型用法,泛型命名约定,以及泛型与接口、函数、类型别名、类等方面的写法,以及泛型默认值等方面介绍了泛型的基本使用,希望能够对你有帮助。

感谢你的阅读,如果你从文章中学到了知识,还请支持一下博主,有任何问题欢迎私信或评论,谢谢!

相关文章
|
7月前
|
JavaScript 前端开发 编译器
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)
135 0
|
7月前
|
JavaScript 编译器
TypeScript中泛型在函数和类中的应用
【4月更文挑战第23天】TypeScript的泛型在函数和类中提供了灵活性,允许处理多种数据类型。了解泛型是掌握TypeScript类型系统的关键。
|
3月前
|
JavaScript 编译器
typescript之泛型
typescript之泛型
135 60
|
2月前
|
JavaScript 前端开发
TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第11天】TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
3月前
|
JavaScript 安全
typeScript进阶(14)_泛型和注意事项
TypeScript中的泛型允许创建可重用的代码。泛型可以定义函数、接口、类,支持传递类型参数,实现类型安全。泛型可以用于数组,约束类型参数必须符合特定的接口,也可以在接口和类中使用。泛型类可以包含多个类型参数,甚至在泛型约束中使用类型参数。
28 1
typeScript进阶(14)_泛型和注意事项
|
2月前
|
JavaScript 安全 前端开发
TypeScript :枚举&字符&泛型
本文介绍了 TypeScript 中的泛型、约束、枚举和字符操作的基本用法。通过示例代码展示了如何定义和使用泛型函数、类和接口,以及如何利用 `keyof` 约束类型。此外,还介绍了枚举的定义和使用,包括常量枚举和外部枚举的区别。最后,简要说明了 `?.` 和 `??` 操作符的用途,帮助处理可能为空的属性和提供默认值。
|
4月前
|
JavaScript 安全 算法
TypeScript:一个好泛型的价值
TypeScript:一个好泛型的价值
|
5月前
|
JavaScript 前端开发 程序员
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
88 0
|
6月前
|
JavaScript
TypeScript 泛型类型
TypeScript 泛型类型
|
6月前
|
JavaScript Java 编译器
TypeScript 泛型
TypeScript 泛型