Skip to content
On this page

TypeScript 类型系统

TypeScript 的核心是其类型系统,它允许开发者在编译时定义和检查类型,从而减少运行时错误。

基本类型详解

原始类型

TypeScript 支持 JavaScript 的所有原始类型:

typescript
// 布尔值
let isCompleted: boolean = true;

// 数字(包括整数、浮点数、十六进制、八进制等)
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

// 字符串
let greeting: string = "Hello, world";

// 数组
let numbers: number[] = [1, 2, 3];
let numbers2: Array<number> = [1, 2, 3]; // 泛型语法

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

特殊类型

typescript
// 枚举
enum Direction {
  Up = 1,
  Down,
  Left,
  Right
}

let direction: Direction = Direction.Up;

// Any(任意类型)
let notSure: any = 4;
notSure = "maybe a string";
notSure = false;

// Void(无返回值)
function warnUser(): void {
  console.log("This is a warning message");
}

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

// Never(永远不会返回值的类型)
function error(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {}
}

// Object
declare function create(o: object | null): void;
create({ prop: 0 });

对象类型

接口(Interface)

typescript
interface User {
  name: string;
  age: number;
  email?: string; // 可选属性
}

let user: User = {
  name: "John",
  age: 30
};

类型别名(Type Alias)

typescript
type Point = {
  x: number;
  y: number;
};

type ID = string | number;

// 与接口的区别
type Window = {
  // 不能重复定义
};

// 接口可以重复定义(合并)
interface Window {
  title: string;
}

interface Window {
  ts: number;
}

联合类型与交叉类型

联合类型

typescript
function formatId(id: number | string) {
  return typeof id === "number" ? id.toString() : id;
}

// 类型守卫
function isString(value: unknown): value is string {
  return typeof value === "string";
}

// 字面量类型
type Size = "small" | "medium" | "large";
type StatusCode = 200 | 400 | 404 | 500;

交叉类型

typescript
interface Colorful {
  color: string;
}

interface Circle {
  radius: number;
}

type ColorfulCircle = Colorful & Circle;

const circle: ColorfulCircle = {
  color: "red",
  radius: 5
};

泛型

typescript
// 泛型函数
function identity<T>(arg: T): T {
  return arg;
}

let output1 = identity<string>("myString");
let output2 = identity("myString"); // 类型推断

// 泛型接口
interface GenericIdentityFn<T> {
  (arg: T): T;
}

// 泛型类
class GenericNumber<T> {
  zeroValue: T;
  add: (x: T, y: T) => T;
}

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

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

类型推断与类型断言

类型推断

typescript
// 基于初始化值的推断
let x = 3; // 推断为 number

// 基于上下文的推断
window.onmousedown = function(mouseEvent) {
  console.log(mouseEvent.button); // 推断为 MouseEvent
};

类型断言

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

// as 语法
let someValue2: any = "this is a string";
let strLength2: number = (someValue2 as string).length;

// 非空断言操作符
function liveDangerously(x?: number | null) {
  console.log(x!.toFixed()); // 告诉 TS x 不是 null 或 undefined
}

高级类型

索引类型

typescript
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
  return names.map(n => o[n]);
}

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

const person: Person = { name: "Jarid", age: 35 };
const values = pluck(person, ["name", "age"]);

映射类型

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

type ReadonlyPerson = Readonly<Person>;
type PartialPerson = Partial<Person>;
type PickPerson = Pick<Person, "name">;
type RecordPerson = Record<"a" | "b", Person>;

类型保护

typescript
// 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 类型保护
interface Padder {
  getPaddingString(): string;
}

class SpaceRepeatingPadder implements Padder {
  constructor(private numSpaces: number) {}
  getPaddingString() {
    return Array(this.numSpaces + 1).join(" ");
  }
}

function usePadder(padder: Padder) {
  if (padder instanceof SpaceRepeatingPadder) {
    padder.numSpaces; // 在这个分支中,TypeScript 知道这是 SpaceRepeatingPadder
  }
}

小结

TypeScript 的类型系统是其最强大的特性之一,通过合理使用各种类型,可以显著提高代码的健壮性和可维护性。掌握这些类型概念对于编写高质量的 TypeScript 代码至关重要。