跳到主要内容

泛型基础

泛型解决什么问题?​

  • 含义: 把类型作为参数, 在调用时才确定;
  • 收益: 逻辑只写一遍, 类型信息随调用点变化, 避免为每种类型重复实现或退化成 any;
  • 语法: 类型参数写在尖括号中, 如 <T>;
function createArray<T>(length: number, value: T): Array<T> {
const result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}

createArray<string>(3, "x"); // ["x", "x", "x"]; 显式指定类型参数
createArray(3, "x"); // 也可由实参推断出 T = string

箭头函数如何写泛型?​

const createArray2 = <T>(length: number, value: T): Array<T> => {
const result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
};
  • 位置: 类型参数写在参数列表之前;
  • 边界: .tsx 中尖括号会被当作 JSX, 需要用 <T,> 或改用函数声明;

如何使用多个类型参数?​

  • 语法: 尖括号内用逗号分隔多个类型参数, 按位置依次绑定;
const swap = <T, U>(tuple: [T, U]): [U, T] => {
return [tuple[1], tuple[0]];
};

泛型参数的默认类型何时生效?​

  • 触发条件: 调用时既没有显式指定类型参数, 编译器也无法从实参推断;
  • 语法: <T = 默认类型>;
const createArray3 = <T = string>(length: number, value: T): Array<T> => {
const result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
};

为什么需要泛型约束?​

  • 问题: 泛型参数在函数内部仍是未知类型, 不能访问任何属性或方法;
  • 目标: 在保持泛化的同时, 声明类型参数至少具备哪些成员;

如何用 extends 声明泛型约束?​

interface Lengthwise {
length: number;
}

const loggingIdentity = <T extends Lengthwise>(arg: T): T => {
console.log(arg.length);
return arg;
};
  • 语法: <T extends 约束类型>;
  • 效果: 实参必须满足约束; 函数体内可以安全访问约束中声明的成员 length;
  • 返回值: T 仍是调用时的具体类型, 不会退化为约束类型;