泛型

Tutorial: TS初级一 Category: TS Published: 2026-04-07 13:58:26 Views: 20 Likes: 0 Comments: 0
  1. 泛型
// 1.基本使用
function demo<T>(arg: T): T {
  // console.log(arg.length);
  return arg;
}
const t1 = demo<string>("hello");
console.log(t1);
const t2 = demo<number>(1);
console.log(t2);

// 2.简化调用 不要用 const
let num = demo(10);
let str = demo("10");

// 3.泛型添加约束
// demo1<T> 微粒一样
function demo1<T>(arg: T[]): T[] {
  console.log(arg.length);
  return arg;
}
demo1([1, 2, 3]);
demo1(["a", "b"]);

// 4.通过接口约束 必须要有length属性
interface ILength {
  length: number;
}
// 还是要看后面的写法
function demo2<T extends ILength>(arg: T): T {
  console.log(arg.length);
  return arg;
}
demo2("hello");
demo2([1, 2, 3]);
demo2({ length: 100, name: "tom" });

// 5.多个泛型变量的情况
function getProp<O, V extends keyof O>(obj: O, value: V) {
  return obj[value];
}
console.log(getProp({ name: "tom", age: 20 }, "name"));
console.log(getProp({ name: "tom", age: 20 }, "age"));
// console.log(getProp({ name: "tom", age: 20 }, "age1"));

// 6.补充:(了解)
console.log(getProp(18, "toFixed"));
console.log(getProp("abc", "split"));
console.log(getProp("abc", 1)); // 此处 1 表示索引
console.log(getProp(["a", "b"], "length"));
console.log(getProp(["a"], 1000));

// 7.泛型接口
interface IDemo<Type> {
  demo: (value: Type) => Type;
  demos: () => Type[];
}
let obj: IDemo<number> = {
  demo(value) {
    return value;
  },
  demos() {
    return [1, 3, 5];
  },
};
console.log(obj.demo(8));
console.log(obj.demos());
  1. 泛型类
// class GenericNumber<NumType> {
//   defaultValue: NumType;
//   add: (x: NumType, y: NumType) => NumType;
//   constructor(value: NumType) {
//     this.defaultValue = value;
//   }
// }
// // 此时, 可以省略 <类型> 不写.因为 TS 可以根据传入的参数自动推导出类型
// const myNum = new GenericNumber(100);
// myNum.defaultValue = 10;

class GenericNumber<NumType> {
  defaultValue: NumType;
  add: (x: NumType, y: NumType) => NumType;
}
// 这种情况下, 推荐明确指定 <类型>.因为 TS 无法推导出类型
const myNum = new GenericNumber();
myNum.defaultValue = 10;
  1. 泛型工具类
// Partial 将所有属性设置为可选
interface Props {
  id: string;
  children: number[];
}
type PartialProps = Partial<Props>;
let p1: Props = {
  id: "",
  children: [1],
};
let p2: PartialProps = {
  //   id: "", // 可以不存在
  children: [1, 3],
};

// Readonly 将所有属性设置为只读
type ReadonlyProps = Readonly<Props>;
let p3: ReadonlyProps = {
  id: "1",
  children: [1, 3],
};
// p3.id = "2"; // 无法修改

// Pick 挑选几个属性作为新类型
interface Props1 {
  id: string;
  title: string;
  children: number[];
}
type PickProps = Pick<Props1, "id" | "title">;
let p4: PickProps = {
  id: "123",
  title: "test",
};

// Record 构造一个对象类型, 属性为 Key, 属性类型为Type
type RecordObj = Record<"a" | "b" | "c", string[]>;
// type RecordObj = {
//   a: string[]
//   b: string[]
//   c: string[]
// }
let obj: RecordObj = {
  a: ["a"],
  b: ["b"],
  c: ["c"],
};
  1. 索引签名类型
interface AnyObject {
  [key: string]: number;
}
let obj: AnyObject = {
  a: 1,
  abc: 124,
  abcde: 12345,
};

//
const arr = [1, 3, 5];
arr.forEach;
interface MyArray<Type> {
  [index: number]: Type;
}
let arr1: MyArray<number> = [1, 3, 5];
arr1[0];
  1. 映射类型
type PropKeys = "x" | "y" | "z" | "a" | "b";
type Type1 = { x: number; y: number; z: number; a: number; b: number };

type Type2 = { [Key in PropKeys]: number };

// 错误演示:
// interface Type3 {
//   [Key in PropKeys]: number
// }

// 使用 keyof
type Props = { a: number; b: string; c: boolean };
type Type3 = { [key in keyof Props]: number };

// 模拟 Partial 类型:
type Props1 = { a: number; b: string; c: boolean };
type TypeA = Props1["a"]; // 索引查询类型
type MyPartial<T> = {
  [P in keyof T]?: T[P];
};
type PartialProps = MyPartial<Props>;

// 其他使用方式:
type TypeA1 = Props1["a" | "b"];
type TypeB1 = Props1[keyof Props];
let p: TypeB1 = false;
Prev: 交叉类型 Next: None