TypeScript 入门指南

TypeScript 入门指南:从 JavaScript 到类型安全

TypeScript是JavaScript的超集,通过静态类型系统为大型项目提供更好的代码质量保障。目前已成为前端开发和Node.js后端开发的主流选择。本文带你快速入门TypeScript核心特性。

一、为什么使用TypeScript

  • 类型安全:在编译阶段捕获类型错误,而不是在运行时崩溃
  • 智能提示:IDE提供精准的代码补全、参数提示、文档提示
  • 重构友好:类型系统保障大规模重构的安全性
  • 更好的文档:类型声明本身就是最好的文档
  • 渐进迁移:可以将现有JavaScript项目逐步迁移到TypeScript

二、基础类型

// 基本类型
let name: string = "Alice";
let age: number = 25;
let isActive: boolean = true;
let nothing: null = null;
let undef: undefined = undefined;

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

// 元组(固定长度和类型的数组)
let pair: [string, number] = ["age", 25];

// 枚举
enum Direction { Up, Down, Left, Right }
let dir: Direction = Direction.Up;

// Any(绕过类型检查,尽量避免使用)
let anything: any = "could be anything";

// Unknown(比any更安全)
let userInput: unknown = "hello";
if (typeof userInput === "string") {
    console.log(userInput.toUpperCase());  // 类型守卫后才能使用
}

// Union类型(联合类型)
let id: string | number = "user-001";
id = 123; // 也合法

// Literal类型(字面量类型)
let direction: "north" | "south" | "east" | "west" = "north";

三、接口与类型别名

// Interface:定义对象结构
interface User {
    id: number;
    name: string;
    email?: string;       // 可选属性
    readonly createdAt: Date; // 只读属性
}

// 类型别名(Type Alias)
type Point = {
    x: number;
    y: number;
};

// 接口继承
interface Admin extends User {
    role: "super" | "normal";
    permissions: string[];
}

// 函数类型
interface Transformer<T, U> {
    (input: T): U;
}

const toString: Transformer<number, string> = (n) => n.toString();

四、泛型(Generics)

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

const num = identity<number>(42);     // 显式指定
const str = identity("hello");         // 类型推断

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

function getLength<T extends HasLength>(item: T): number {
    return item.length;
}

// 泛型类
class Stack<T> {
    private items: T[] = [];
    push(item: T): void { this.items.push(item); }
    pop(): T | undefined { return this.items.pop(); }
    isEmpty(): boolean { return this.items.length === 0; }
}

const numStack = new Stack<number>();
numStack.push(1);
numStack.push(2);

五、高级类型

// Partial:所有属性变为可选
type PartialUser = Partial<User>;  // { id?: number; name?: string; ... }

// Required:所有属性变为必填
type RequiredUser = Required<User>;

// Pick:选取部分属性
type UserPreview = Pick<User, "id" | "name">;

// Omit:排除部分属性
type UserWithoutId = Omit<User, "id">;

// Record:创建键值类型的对象
type UserMap = Record<string, User>;

// Conditional类型
type IsString<T> = T extends string ? true : false;
type R1 = IsString<string>;  // true
type R2 = IsString<number>;  // false

六、装饰器(Decorators)

// 类装饰器
function Singleton<T extends { new (...args: any[]): {} }>(cls: T) {
    let instance: T;
    return class extends cls {
        constructor(...args: any[]) {
            if (!instance) {
                super(...args);
                instance = this as any;
            }
            return instance;
        }
    };
}

// 方法装饰器(常用于日志、缓存、权限控制)
function log(target: any, key: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args: any[]) {
        console.log(`Calling ${key} with`, args);
        const result = original.apply(this, args);
        console.log(`${key} returned`, result);
        return result;
    };
    return descriptor;
}

七、配置tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,           // 开启所有严格模式检查
    "noImplicitAny": true,    // 禁止隐式any
    "strictNullChecks": true, // null和undefined需要显式处理
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,      // 生成.d.ts类型声明文件
    "esModuleInterop": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

八、总结

TypeScript的学习曲线不陡峭,基础类型和接口可以在几小时内掌握。建议从现有JavaScript项目的入口文件开始,逐步添加类型注解,体验类型系统带来的红利。对于新项目,直接使用TypeScript是目前最佳实践,可以从项目初期就享受类型安全的保障。