TypeScript 类型系统完全指南

79 阅读2分钟

TypeScript 类型系统完全指南

目录

  1. 基本类型
  2. 对象类型
  3. 数组和元组
  4. 特殊类型
  5. 类型断言和类型守卫
  6. 高级类型
  7. 实用工具类型

基本类型

number

let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let big: bigint = 100n;  // ES2020

string

let color: string = "blue";
let fullName: string = `Bob Bobbington`;
let sentence: string = `Hello, my name is ${fullName}`;

boolean

let isDone: boolean = false;
let isActive: boolean = true;

null 和 undefined

let u: undefined = undefined;
let n: null = null;

symbol

let sym1: symbol = Symbol();
let sym2: symbol = Symbol("key");

对象类型

object

// 普通对象
let obj: object = { prop: 0 };

// 具体的对象类型
interface Point {
  x: number;
  y: number;
}
let point: Point = { x: 10, y: 20 };

// 可选属性
interface Config {
  color?: string;
  width?: number;
}

// 只读属性
interface ReadOnlyPoint {
  readonly x: number;
  readonly y: number;
}

class

class Animal {
  private name: string;
  protected age: number;
  public type: string;

  constructor(name: string, age: number, type: string) {
    this.name = name;
    this.age = age;
    this.type = type;
  }
}

interface

interface Vehicle {
  brand: string;
  model: string;
  year: number;
  start(): void;
  stop(): void;
}

class Car implements Vehicle {
  constructor(
    public brand: string,
    public model: string,
    public year: number
  ) {}

  start() { console.log('Starting...'); }
  stop() { console.log('Stopping...'); }
}

数组和元组

数组

// 类型+方括号
let list1: number[] = [1, 2, 3];

// 泛型数组
let list2: Array<number> = [1, 2, 3];

// 多类型数组
let list3: (number | string)[] = [1, "hello", 2];

// 只读数组
let readOnlyList: ReadonlyArray<number> = [1, 2, 3];

元组

// 固定长度和类型的数组
let tuple: [string, number] = ["hello", 10];

// 可选元素的元组
let optionalTuple: [string, number?] = ["hello"];

// 剩余元素��元组
let restTuple: [number, ...string[]] = [1, "hello", "world"];

特殊类型

any

let notSure: any = 4;
notSure = "maybe a string";
notSure = false;

unknown

let value: unknown = 4;
if (typeof value === "string") {
    console.log(value.toUpperCase());
}

void

function warnUser(): void {
    console.log("This is a warning message");
}

never

// 永远不会返回的函数
function error(message: string): never {
    throw new Error(message);
}

// 永远不会有返回值的循环
function infiniteLoop(): never {
    while (true) {}
}

类型断言和类型守卫

类型断言

// 尖括号语法
let someValue: unknown = "this is a string";
let strLength: number = (<string>someValue).length;

// as 语法
let otherValue: unknown = "this is a string";
let otherLength: number = (otherValue as string).length;

类型守卫

// typeof 类型守卫
function padLeft(value: string, padding: string | number) {
    if (typeof padding === "number") {
        return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
        return padding + value;
    }
    throw new Error(`Expected string or number, got '${padding}'.`);
}

// instanceof 类型守卫
class Bird {
    fly() { console.log("flying..."); }
}
class Fish {
    swim() { console.log("swimming..."); }
}

function move(pet: Bird | Fish) {
    if (pet instanceof Bird) {
        pet.fly();
    } else {
        pet.swim();
    }
}

高级类型

联合类型

let unionType: string | number;
unionType = "hello";
unionType = 42;

交叉类型

interface BusinessPartner {
    name: string;
    credit: number;
}

interface Identity {
    id: number;
    email: string;
}

type Employee = BusinessPartner & Identity;

字面量类型

// 字符串字面量
type Easing = "ease-in" | "ease-out" | "ease-in-out";

// 数字字面量
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;

索引类型

interface StringArray {
    [index: number]: string;
}

let myArray: StringArray = ["Bob", "Fred"];

映射类型

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

type Partial<T> = {
    [P in keyof T]?: T[P];
};

实用工具类型

Partial

interface Todo {
    title: string;
    description: string;
}

function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
    return { ...todo, ...fieldsToUpdate };
}

Readonly

interface Config {
    host: string;
    port: number;
}

const config: Readonly<Config> = {
    host: "localhost",
    port: 3000
};

Record

interface PageInfo {
    title: string;
}

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
    home: { title: "Home" },
    about: { title: "About" },
    contact: { title: "Contact" }
};

Pick

interface Todo {
    title: string;
    description: string;
    completed: boolean;
}

type TodoPreview = Pick<Todo, "title" | "completed">;

Omit

interface Todo {
    title: string;
    description: string;
    completed: boolean;
}

type TodoInfo = Omit<Todo, "completed">;

最佳实践

  1. 尽可能使用具体的类型而不是 any
  2. 利用类型推断减少冗余的类型注解
  3. 使用接口定义对象结构
  4. 使用类型守卫进行类型收窄
  5. 合理使用工具类型简化代码

总结

TypeScript 的类型系统非常强大,包括:

  • 基本类型:number, string, boolean 等
  • 对象类型:interface, class 等
  • 数组和元组类型
  • 特殊类型:any, unknown, void, never
  • 高级类型:联合类型、交叉类型等
  • 工具类型:Partial, Readonly, Record 等

合理使用这些类型可以:

  1. 提高代码的可维护性
  2. 减少运行时错误
  3. 提供更好的开发体验
  4. 增强代码的可读性