泛型
泛型实例化,就是在引用泛型类型时,传入一个实际类型参数作为形式类型参数的值。多个实际类型之间使用逗号去分割。我们可以约束泛型的形式类型参数。使用语法如下,其中第一个参数表示类型参数名,第二个表示继承关键字,第三个表示一个类型。形式类型参数可以同时定义泛型约束和默认类型,但是默认类型需要满足泛型约束。如果定义泛型约束那么传入的实际类型参数也需要符合泛型约束。我们在使用泛型约束时,允许引用当前形式类型参数列表中的其他类型参数。
<TypeParameter extends ConstrainType>
每个类型参数都有基约束,类型参数的实际类型一定是基约束的子类型。函数签名分为调用签名和构造签名。都支持定义类型参数。当函数中接收两个相同类型的参数,函数返回值类型是数组而且数组元素类型和参数类型时相同的。下面案例中peo函数可以接收两个参数,参数b可以是任意类型的数组。参数f是一个函数,返回值和参数b的类型时一样的。peo的函数返回值是f返回值类型的数组。编译器中可以自动识别泛型函数的实际类型参数,即使我们没有传参类型,编译器也能识别出来。
function peo<T, U>(b: T[], f: (x: T) => U): U[] {
return b.map(f)
}
const b: boolean[] = peo<number, boolean>([6, 7, 8], n => !!n);
泛型函数中我们需要注意的是当一个函数不仅可以定义为非泛型函数又可以定义泛型函数,我们一般使用非泛型函数的形式。
当定义接口带类型参数就是泛型接口,形式类型参数放在接口的后面。在引用泛型接口时,如果类型参数没有默认类型,我们必须指定实际类型参数。泛型类型别名指的就是类型别名中带有类型参数。泛型类型别名定义和泛型接口一样参数放在别名之后。在引用泛型类型别名时,也必须指定实际参数类型。泛型类的定义和泛型接口和泛型类型一样。我们需要注意的是在类的静态成员中不允许引用类型参数,不然编译会报错。这是因为类的静态成员时类构造函数类型的一部分。
interface Peo<T> extends Array<T> {
x: T | undefined;
y: T | undefined;
}