Skip to main content

TypeScript 类型系统深入详解

·967 words·2 mins

概述
#

TypeScript 是 JavaScript 的超集,添加了静态类型系统。本文深入讲解 TypeScript 的类型系统。

基础类型
#

基本类型
#

// 布尔值
let isActive: boolean = true;

// 数值
let age: number = 25;
let pi: number = 3.14;

// 字符串
let name: string = "Alice";
let message: string = `Hello, ${name}`;

// 数组
let numbers: number[] = [1, 2, 3];
let words: Array<string> = ["a", "b", "c"];

// 元组
let tuple: [string, number] = ["Alice", 25];

// 枚举
enum Color { Red, Green, Blue }
let color: Color = Color.Red;

// Any
let anything: any = "hello";
anything = 123;

// Void
function log(message: string): void {
  console.log(message);
}

// Null 和 Undefined
let n: null = null;
let u: undefined = undefined;

// Never
function error(message: string): never {
  throw new Error(message);
}

// Object
function create(o: object): void {
  console.log(o);
}

类型推断
#

let count = 10; // 推断为 number
let message = "Hello"; // 推断为 string

// 显式类型覆盖推断
let id: number | string = 123;
id = "abc";

复合类型
#

接口 (Interface)
#

interface User {
  id: number;
  name: string;
  email?: string; // 可选属性
  readonly createdAt: Date; // 只读属性
}

const user: User = {
  id: 1,
  name: "Alice",
  createdAt: new Date()
};

// 函数类型
interface SearchFunc {
  (source: string, subString: string): boolean;
}

const search: SearchFunc = (src, sub) => src.includes(sub);

// 索引签名
interface StringArray {
  [index: number]: string;
}

const arr: StringArray = ["a", "b", "c"];

类 (Class)
#

class Animal {
  name: string;
  protected age: number;

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

  speak(sound: string): void {
    console.log(`${this.name} makes ${sound}`);
  }
}

class Dog extends Animal {
  constructor(name: string, age: number) {
    super(name, age);
  }

  bark(): void {
    this.speak("Woof");
  }
}

const dog = new Dog("Buddy", 3);
dog.bark();

类型别名 (Type Alias)
#

type ID = number | string;
type User = {
  id: ID;
  name: string;
};
type Callback = (data: any) => void;

// 联合类型
type JSONValue = string | number | boolean | null | JSONObject | JSONArray;

// 交叉类型
type Admin = User & { adminLevel: number };

高级类型
#

泛型 (Generic)
#

// 基础泛型
function identity<T>(arg: T): T {
  return arg;
}

const num = identity<number>(42);
const str = identity<string>("hello");

// 泛型接口
interface Cache<T> {
  get(key: string): T | null;
  set(key: string, value: T): void;
}

// 泛型类
class Queue<T> {
  private items: T[] = [];

  enqueue(item: T): void {
    this.items.push(item);
  }

  dequeue(): T | undefined {
    return this.items.shift();
  }
}

// 泛型约束
interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

条件类型 (Conditional Type)
#

type IsString<T> = T extends string ? true : false;
type IsNumber<T> = T extends number ? true : false;

type A = IsString<string>; // true
type B = IsString<number>; // false

// 分布式条件类型
type Flat<T> = T extends any[] ? T[number] : T;

// infer 关键字
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

映射类型 (Mapped Type)
#

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

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

// Pick
type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

// Omit
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

// 自定义映射
type Nullable<T> = {
  [P in keyof T]: T[P] | null;
};

工具类型
#

// Partial - 所有属性设为可选
interface User { id: number; name: string }
type PartialUser = Partial<User>;

// Required - 所有属性设为必选
type RequiredUser = Required<PartialUser>;

// Readonly - 所有属性设为只读
type ReadonlyUser = Readonly<User>;

// Record - 构建对象类型
type StringMap<T> = Record<string, T>;
const map: StringMap<number> = { a: 1, b: 2 };

// Exclude - 从联合类型中排除
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"

// Extract - 从联合类型中提取
type T2 = Extract<"a" | "b" | "c", "a" | "b">; // "a" | "b"

// NonNullable - 排除 null 和 undefined
type T3 = NonNullable<string | null | undefined>; // string

// Parameters - 获取函数参数类型
type T4 = Parameters<(x: string, y: number) => void>; // [string, number]

// ReturnType - 获取函数返回类型
type T5 = ReturnType<() => string>; // string

最佳实践
#

  1. 启用 strict 模式 - 更严格的类型检查
  2. 避免 any - 使用 unknown 或泛型
  3. 使用接口而不是类型别名 - 接口可扩展
  4. 泛型约束 - 使用 extends 限制类型
  5. 工具类型复用 - 减少重复代码

总结
#

TypeScript 类型系统强大且灵活,合理使用可以显著提升代码质量。