概述

TypeScript 的类型系统是其最强大的特性之一。本教程将深入学习 TypeScript 的各种类型,包括基础类型、对象类型、函数类型等。

基础类型

原始类型

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

// 数字(所有数字都是浮点数)
let age: number = 25;
let pi: number = 3.14159;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

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

// BigInt
let bigNumber: bigint = 100n;
let anotherBig: bigint = BigInt(100);

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

// null 和 undefined
let nothing: null = null;
let notDefined: undefined = undefined;

// void(表示没有返回值)
function log(message: string): void {
    console.log(message);
}

// never(表示永不返回)
function error(message: string): never {
    throw new Error(message);
}

对象类型

接口定义对象

// 基本接口
interface Person {
    name: string;
    age: number;
}

// 使用接口
const person: Person = {
    name: "Alice",
    age: 25
};

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

const user: User = {
    id: 1,
    name: "Bob"
    // email 和 phone 是可选的
};

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

const point: Point = { x: 10, y: 20 };
// point.x = 15;  // 错误:只读属性不能修改

类型别名定义对象

// 使用类型别名
type User = {
    id: number;
    name: string;
    email?: string;
};

const newUser: User = {
    id: 2,
    name: "Charlie"
};

数组类型

基本数组类型

// 类型注解语法
let numbers: number[] = [1, 2, 3, 4, 5];
let strings: string[] = ["a", "b", "c"];
let booleans: boolean[] = [true, false, true];

// 泛型语法
let numbers2: Array<number> = [1, 2, 3, 4, 5];
let strings2: Array<string> = ["a", "b", "c"];

// 只读数组
const readOnlyNumbers: readonly number[] = [1, 2, 3];
// readOnlyNumbers.push(4);  // 错误:只读数组不能修改

const readOnlyNumbers2: ReadonlyArray<number> = [1, 2, 3];

元组类型

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

// 访问元素
console.log(tuple[0]);  // "Alice"
console.log(tuple[1]);  // 25

// 可选元素
let optionalTuple: [string, number, boolean?] = ["Bob", 30];
optionalTuple = ["Bob", 30, true];

// 剩余元素
let restTuple: [string, ...number[]] = ["Alice", 1, 2, 3, 4];

函数类型

函数声明

// 函数声明
function add(a: number, b: number): number {
    return a + b;
}

// 箭头函数
const multiply = (a: number, b: number): number => {
    return a * b;
};

// 函数表达式
const subtract: (a: number, b: number) => number = (a, b) => {
    return a - b;
};

函数类型别名

// 定义函数类型
type MathOperation = (a: number, b: number) => number;

// 使用函数类型
const add: MathOperation = (a, b) => a + b;
const multiply: MathOperation = (a, b) => a * b;

// 作为参数
function calculate(operation: MathOperation, a: number, b: number): number {
    return operation(a, b);
}

console.log(calculate(add, 5, 3));      // 8
console.log(calculate(multiply, 5, 3)); // 15

可选参数和默认参数

// 可选参数
function greet(name: string, greeting?: string): string {
    return greeting ? `${greeting}, ${name}!` : `Hello, ${name}!`;
}

console.log(greet("Alice"));           // "Hello, Alice!"
console.log(greet("Bob", "Hi"));     // "Hi, Bob!"

// 默认参数
function createName(first: string, last: string = "Smith"): string {
    return `${first} ${last}`;
}

console.log(createName("Alice"));      // "Alice Smith"
console.log(createName("Bob", "Jones")); // "Bob Jones"

剩余参数

// 剩余参数
function sum(...numbers: number[]): number {
    return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3));        // 6
console.log(sum(1, 2, 3, 4, 5));  // 15

函数重载

// 函数重载
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: any, b: any): any {
    return a + b;
}

console.log(add(1, 2));        // 3
console.log(add("Hello", "World")); // "HelloWorld"

联合类型和交叉类型

联合类型

// 联合类型
type ID = string | number;

function printId(id: ID) {
    console.log(`ID: ${id}`);
}

printId(101);        // "ID: 101"
printId("abc-123");  // "ID: abc-123"

// 更复杂的联合类型
type Success = {
    status: "success";
    data: any;
};

type Error = {
    status: "error";
    message: string;
};

type Result = Success | Error;

function handleResult(result: Result) {
    if (result.status === "success") {
        console.log("Data:", result.data);
    } else {
        console.log("Error:", result.message);
    }
}

交叉类型

// 交叉类型
type Person = {
    name: string;
    age: number;
};

type Employee = {
    employeeId: number;
    department: string;
};

type EmployeePerson = Person & Employee;

const employee: EmployeePerson = {
    name: "Alice",
    age: 25,
    employeeId: 1001,
    department: "Engineering"
};

字面量类型

字符串字面量

// 字符串字面量类型
type Direction = "up" | "down" | "left" | "right";

function move(direction: Direction) {
    console.log(`Moving ${direction}`);
}

move("up");    // 正确
// move("diagonal");  // 错误

// 模板字符串字面量
type EventName<T extends string> = `on${Capitalize<T>}`;

// 登录事件
type LoginEvent = EventName<"login">;  // "onLogin"
type LogoutEvent = EventName<"logout">; // "onLogout"

数字字面量

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

function rollDice(): DiceRoll {
    return Math.floor(Math.random() * 6) + 1 as DiceRoll;
}

// 误差数字
type ApproximateNumber = number | `${number}.${number}`;

布尔字面量

// 布尔字面量类型
type Success = true;
type Failure = false;

function checkResult(result: Success | Failure) {
    if (result) {
        console.log("操作成功");
    } else {
        console.log("操作失败");
    }
}

类型推断

基础类型推断

// 自动推断类型
let x = 3;         // number
let y = "hello";    // string
let z = true;       // boolean

// 最佳通用类型
let arr = [0, 1, null];  // (number | null)[]

上下文类型

// 上下文类型推断
window.onmousedown = function(mouseEvent) {
    console.log(mouseEvent.button);  // 自动推断为 MouseEvent
};

// 函数参数
function createMap(pairs: [string, number][]) {
    const map: Record<string, number> = {};
    
    for (const [key, value] of pairs) {
        map[key] = value;  // 自动推断 value 为 number
    }
    
    return map;
}

类型守卫

typeof 类型守卫

// typeof 类型守卫
function printLength(value: string | number) {
    if (typeof value === "string") {
        console.log(value.length);
    } else {
        console.log(value.toFixed(2));
    }
}

printLength("hello"); // 5
printLength(3.14159); // "3.14"

instanceof 类型守卫

// instanceof 类型守卫
function logValue(value: Date | string[]) {
    if (value instanceof Date) {
        console.log(value.toISOString());
    } else {
        console.log(value.join(", "));
    }
}

logValue(new Date());
logValue(["a", "b", "c"]);

自定义类型守卫

// 自定义类型守卫
interface Fish {
    swim(): void;
}

interface Bird {
    fly(): void;
}

function isFish(pet: Fish | Bird): pet is Fish {
    return (pet as Fish).swim !== undefined;
}

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

类型断言

类型断言语法

// 尖括号语法
let value: any = "hello world";
let strLength: number = (<string>value).length;

// as 语法(推荐)
let strLength2: number = (value as string).length;

// 非空断言
function getEmail(email: string | null | undefined): string {
    return email!;
}

const 断言

// const 断言
const config = {
    endpoint: "https://api.example.com",
    timeout: 5000
} as const;

// 推断为具体字面量类型
type Config = typeof config;
// type Config = {
//     readonly endpoint: "https://api.example.com";
//     readonly timeout: 5000;
// }

映射类型

基础映射类型

// 将所有属性变为可选
type Partial<T> = {
    [P in keyof T]?: T[P];
};

interface User {
    id: number;
    name: string;
    email: string;
}

type PartialUser = Partial<User>;
// {
//     id?: number;
//     name?: string;
//     email?: string;
// }

// 将所有属性变为必需
type Required<T> = {
    [P in keyof T]-?: T[P];
};

// 将所有属性变为只读
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

条件类型

// 条件类型
type NonNullable<T> = T extends null | undefined ? never : T;

type Result1 = NonNullable<string | null>;  // string
type Result2 = NonNullable<number | undefined>; // number

// 提取类型
type Flatten<T> = T extends any[] ? T[number] : T;

type Flat1 = Flatten<string[]>;  // string
type Flat2 = Flatten<number>;    // number

总结

本教程详细介绍了 TypeScript 的类型系统:

  1. 基础类型

    • 原始类型:string、number、boolean、bigint、symbol
    • 特殊类型:null、undefined、void、never
  2. 对象类型

    • 接口定义对象结构
    • 可选属性和只读属性
    • 类型别名
  3. 数组类型

    • 基本数组类型
    • 只读数组
    • 元组类型
  4. 函数类型

    • 函数声明和表达式
    • 函数类型别名
    • 可选参数、默认参数、剩余参数
    • 函数重载
  5. 联合类型和交叉类型

    • 联合类型:值的并集
    • 交叉类型:类型的交集
  6. 字面量类型

    • 字符串字面量
    • 数字字面量
    • 布尔字面量
  7. 类型推断

    • 基础类型推断
    • 上下文类型推断
  8. 类型守卫

    • typeof 类型守卫
    • instanceof 类型守卫
    • 自定义类型守卫
  9. 类型断言

    • 类型断言语法
    • 非空断言
    • const 断言
  10. 映射类型

    • 基础映射类型
    • 条件类型

TypeScript 的类型系统非常强大,掌握这些类型知识将帮助你编写更安全、更可维护的代码。

下一步

在下一教程中,我们将深入学习 TypeScript 的接口和高级类型,包括:

  • 接口的高级特性

  • 抽象类

  • 访问修饰符

  • 继承和多态

继续学习 TypeScript,掌握这门强大语言的更多特性!