阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 泛型基础概念

泛型基础概念

作者:陈川 阅读数:46289人阅读 分类: TypeScript

泛型是什么

泛型是编程语言中一种强大的特性,允许在定义函数、接口或类时不预先指定具体类型,而是在使用时再指定。TypeScript中的泛型提供了代码复用和类型安全之间的平衡。通过泛型,可以创建可重用的组件,这些组件能够支持多种类型而不牺牲类型检查。

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

let output1 = identity<string>("hello");
let output2 = identity<number>(42);

泛型变量

在泛型函数内部,类型变量T代表任意类型。编译器要求必须正确使用这些泛型变量。当使用泛型创建类似数组这样的结构时,TypeScript知道数组方法的存在。

function loggingIdentity<T>(arg: T[]): T[] {
    console.log(arg.length);
    return arg;
}

function loggingIdentity2<T>(arg: Array<T>): Array<T> {
    console.log(arg.length);
    return arg;
}

泛型类型

泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面。可以使用不同的泛型参数名,只要数量和使用方式对应即可。

let myIdentity: <T>(arg: T) => T = identity;
let myIdentity2: <U>(arg: U) => U = identity;

interface GenericIdentityFn {
    <T>(arg: T): T;
}

let myIdentity3: GenericIdentityFn = identity;

泛型类

泛型类看上去与泛型接口差不多,泛型类使用<>括起泛型类型,跟在类名后面。类有两部分:静态部分和实例部分,泛型类指的是实例部分的类型。

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = function(x, y) { return x + y; };

泛型约束

有时候需要限制泛型的类型范围,这时可以使用extends关键字来实现泛型约束。通过定义一个接口来描述约束条件,然后让泛型类型扩展这个接口。

interface Lengthwise {
    length: number;
}

function loggingIdentity3<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}

loggingIdentity3(3);  // 错误,数字没有.length属性
loggingIdentity3({length: 10, value: 3}); // 正确

在泛型约束中使用类型参数

一个类型参数可以被另一个类型参数所约束。比如现在想要用属性名从对象里获取这个属性,并且需要确保这个属性存在于对象上。

function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };

getProperty(x, "a"); // 正确
getProperty(x, "m"); // 错误:m不在x的key中

泛型中使用类类型

在TypeScript使用泛型创建工厂函数时,需要引用构造函数的类类型。通过原型属性推断并约束构造函数与类实例的关系。

class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}

createInstance(Lion).keeper.nametag;
createInstance(Bee).keeper.hasMask;

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:模块最佳实践

下一篇:泛型函数定义

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌