Typescript进阶

89 阅读3分钟

高阶类型

泛型

可以在编写代码时使用参数化类型,使得代码可以适用于多种不同类型的数据

// 函数泛型
function identity<T>(arg: T): T {
 return arg;
}
// 使用
let output1 = identity<string>("hello"); // output1 的类型为 string 
let output2 = identity<number>(123); // output2 的类型为 number

// 接口泛型
interface Param<T> {
    id: number;
    data: T
}
// 使用
const param1: Param<number[]> = {id: 1, data: [1,2,3]}
const param2: Param<string> = {id: 1, data: 'TEST STRING'}

联合类型

表示这个类型可以是连接的类型中的任意一个

type NumericType = number | bigint;

interface Circle {
    area: bigint;
    radius: number;
}

interface Rectangle {
    area: number;
    width: number;
    height: number;
}

type Shape = Circle | Rectangle;

declare const s: Shape
s.area; // bigint | number
s.width; // 错误
s.radius; // 错误

// 解决方案:使用in操作符或者类型断言
if ('width' in s) {
    console.log(s.width)
}
(s as Circle).radius

交叉类型

对多个类型进行合并,表示这个类型同时具有所有连接的类型的特性

interface User {
  name: string;
  age: number;
}

interface Admin {
  name: string;
  role: string;
}

type UserAdmin = User & Admin;

const userAdmin: UserAdmin = { name: "Alice", age: 30, role: "admin" };
// UserAdmin 是 User 和 Admin 的交叉类型,表示一个用户和管理员的组合类型。
// userAdmin 对象必须同时包含 name、age 和 role 属性

元组

是一种表示具有固定数量和类型的元素的数组类型。元组类型使用方括号 [] 来表示,其中每个元素的类型由逗号分隔

// 示例1
let x: [string, number];
x = ["hello", 10]; // OK
x = [10, "hello"]; // Error

// 示例2
// Point 是一个包含两个数字元素的元组类型
type Point = [number, number];

function distance(p1: Point, p2: Point) {
  const dx = p1[0] - p2[0];
  const dy = p1[1] - p2[1];
  return Math.sqrt(dx ** 2 + dy ** 2);
}

索引类型

// 语法
type PropertyType = ObjectType[Key];

// 示例
type Person = {
  name: string;
  age: number;
  location: string;
}

type NameType = Person['name']; // string
type NameOrAgeType = Person['name' | 'age']; // string | number

映射类型

是一种强大的工具,可以基于已有类型创建新的类型。通过映射类型,你可以对一个类型的所有属性进行变换或操作

// 语法
type MappedType<T> = {
  [P in keyof T]: T[P];
};

// 常见的工具类型就是通过映射类型实现的。举例:
// Partial
type Partial<T> = {
  [P in keyof T]?: T[P];
};

// 示例
interface Person {
  name: string;
  age: number;
}

type PartialPerson = Partial<Person>; 
// PartialPerson 的类型为 { name?: string; age?: number; }

// Required
type Required<T> = {
  [P in keyof T]-?: T[P];
};

// 示例
interface PartialPerson {
  name?: string;
  age?: number;
}

type RequiredPerson = Required<PartialPerson>;
// RequiredPerson 的类型为 { name: string; age: number; }

// Readonly
type Readonly<T> = {
  [P in keyof T]: Readonly<T[P]>;
};

// 示例
interface Person {
  name: string;
  age: number;
}

type ReadonlyPerson = Readonly<Person>;
// ReadonlyPerson 的类型为 { readonly name: string; readonly age: number; }

工具类型

Pick<T,K>

从对象类型中选取给定的属性

interface A {
    x: number;
    y: number;
}

type T0 = Pick<A,'x'> // {x: number}
type T1 = Pick<A, 'x'| 'y'> // {x: number, y: number}

Omit<T,K>

从对象类型中剔除给定的属性

interface A {
    x: number;
    y: number;
}
type T0 = Omit<A,'y'>// {x: number}
type T1 = Omit<A, 'x'| 'y'> // {x: number, y: number}

// Omit的实现
type Omit<T, K extends keyof T> = {
  [P in Exclude<keyof T, K>]: T[P];
};

Exclude<T,U>

从联合类型中剔除给定的属性

type T = 'a' | 'b' | 'c'
type U = 'b' | 'c'

type T0 = Exclude<T,U> // 'a'

Extract<T,U>

从联合类型中选取给定的属性

type T = 'a' | 'b' | 'c'
type U = 'b' | 'c'
type M = 'b' | 'd'

type T0 = Extract<T,U> // 'b' | 'c'
type T1 = Extract<T,M> // 'b'

类型查询操作

typeof

typeof 关键字用于获取一个值的类型。例如:

const x = 42;
type XType = typeof x; // XType 的类型为 number

keyof

keyof 关键字用于获取一个类型的所有属性名。例如:

interface Person {
    name: string;
    age: number;
}

type PersonKeys = keyof Person; // PersonKeys 的类型为 "name" | "age"

in

in 关键字用于判断一个属性名是否属于一个类型。例如:

interface Person {
    name: string;
    age: number;
}

type HasName = "name" in Person; // HasName 的类型为 true
type HasAddress = "address" in Person; // HasAddress 的类型为 false

extends

extends 关键字用于判断一个类型是否是另一个类型的子类型。例如:

interface Animal {
    name: string;
}

interface Dog extends Animal {
    bark(): void;
}

type IsDog = Dog extends Animal ? true : false; // IsDog 的类型为 true
type IsAnimal = Animal extends Dog ? true : false; // IsAnimal 的类型为 false

typeof keyof

typeof keyof 结合使用可以用于获取一个值的所有属性名。例如:

const person = {
    name: "Alice",
    age: 30,
    location: "New York"
};

type PersonKeys = typeof person[keyof typeof person]; // PersonKeys 的类型为 "name" | "age" | "location"