这里是前端程序员小张!
人海茫茫,感谢这一秒你看到这里。希望我的文章对你的有所帮助!
愿你在未来的日子,保持热爱,奔赴山海!
软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像C#和Java这样的语言中,可以使用
泛型
来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
软件工程的主要目的是构建不仅仅明确和一致的API,还要让你的代码具有很强的可重用性:
什么是类型的参数化?
我们来提一个需求:封装一个函数,传入一个参数,并且返回这个参数;
//TypeScript的思维方式,要考虑这个参数和返回值的类型需要一致
function fn(arg: number): number {
return arg;
}
上面的代码虽然实现了,但是不适用于其他类型,比如string、boolean、自定义类等类型;
function fn(arg: any): any {
return arg;
}
使用any
类型会导致这个函数可以接收任何类型的arg
参数,这样就丢失了类型信息
因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了 类型变量,它是一种特殊的变量,只用于表示类型而不是值。
function fn<Type>(arg: Type): Type {
return arg;
}
Type
。Type
帮助我们捕获用户传入的类型(比如:number
),之后我们就可以使用这个类型。 之后我们再次使用了 Type
当做返回值类型。我们把这个版本的
fn
函数叫做泛型,因为它可以适用于多个类型。不同于使用
any
,它不会丢失信息,像第一个例子那像保持准确性,传入数值类型并返回数值类型。
我们定义了泛型函数后,可以用两种方法使用。
fn<string>("hello world")
fn<number>(123)
let message1 = fn("hello world")
let message2 = fn(123)
当然我们也可以传入多个类型:
function fn<T, E>(a1: T, a2: E) {}
平时在开发中我们可能会看到一些常用的名称:
在定义接口的时候我们也可以使用泛型:
interface IFn<T> {
(arg: T): T;
}
function fn<T>(arg: T): T {
return arg;
}
let myFn: IFn<number> = fn;
IFn
的时候,还得传入一个类型参数来指定泛型类型(这里是:number
),锁定了之后代码里使用的类型。泛型类看上去与泛型接口差不多。 泛型类使用( <>
)括起泛型类型,跟在类名后面。
class Point<T> {
x: T;
y: T;
constructor(x: T, y: T) {
this.x = x;
this.y = y;
}
}
const p1 = new Point(10, 20);
const p2 = new Point<number>(20, 30);
const p3: Point<number> = new Point(40, 60);
我们有时候想操作某类型的一组值,并且我们知道这组值具有什么样的属性
我们希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中:
在上述例子中,我们想访问arg
的length
属性,但是编译器并不能证明每种类型都有length
属性,所以就报错了
比如string和array都是有length的,或者某些对象也是会有length属性的;
那么只要是拥有length的属性都可以作为我们的参数类型,那么应该如何操作呢?为此,我们需要列出对于T的约束要求。
我们定义一个接口来描述约束条件。 创建一个包含 .length
属性的接口,使用这个接口和extends
关键字来实现约束:
interface TLength {
length: number;
}
function getLength<T extends TLength>(args: T) {
return args.length;
}
现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
getLength(3) // Argument of type 'number' is not assignable to parameter of type 'ILength'.
我们需要传入符合约束类型的值
console.log(getLength("hello"))
console.log(getLength(["abe", "de"]))
console.log(getLength({length: 10, name: "zhang"}))