This repository has been archived on 2026-05-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
obsidian/FRONTEND/TypeScript 基础.md
T

3.8 KiB
Raw Blame History

tags, create time
tags create time
前端
TypeScript
基础
2026-04-24 18:41

TypeScript 基础

概述

TypeScript 是 JavaScript 的超集,在 JS 的基础上增加了类型系统。它的核心理念:用类型在编译阶段捕获错误,而不是在运行时才发现 bug。

思考题:JavaScript 是动态类型语言,TypeScript 是静态类型语言——它们到底有什么区别?为什么大型前端项目必须用 TypeScript?

正文

1. 类型注解

// 基本类型注解
let userName: string = "Alice";
let age: number = 25;
let isActive: boolean = true;
let scores: number[] = [90, 85, 92];          // 数组
let tuple: [string, number] = ["Alice", 25];   // 元组

// 对象类型
interface User {
    name: string;
    age: number;
    email?: string;          // ? 表示可选属性
}

const user: User = {
    name: "Alice",
    age: 25,
    email: "alice@example.com",
};

提问: string 和 String(首字母小写 vs 大写)有什么区别?为什么 TS 用小写?

2. 联合类型与类型守卫

// 联合类型:一个变量可以是多种类型
let value: string | number = "hello";
value = 42;                  // ✅ 合法
value = true;                // ❌ 编译错误

// 类型守卫:在运行时判断具体类型
function processValue(input: string | number) {
    if (typeof input === "string") {
        return input.toUpperCase();  // TS 知道这里是 string
    }
    return input.toFixed(2);         // TS 知道这里是 number
}

// 自定义类型守卫
function isUser(obj: unknown): obj is User {
    return typeof obj === "object" && obj !== null && "name" in obj;
}

3. 接口(Interface)vs 类型别名(Type Alias)

// Interface:适合定义对象形状,可扩展
interface Animal {
    name: string;
}

interface Dog extends Animal {
    breed: string;
}

// Type Alias:更灵活,可用于联合类型、元组等
type ID = string | number;
type Point = [number, number];
type EventHandler = (event: MouseEvent) => void;

核心区别: Interface 可以被合并(declaration merging),Type Alias 不能。定义对象形状优先用 Interface,复杂类型用 Type。

4. 泛型(Generics)

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

identity<string>("hello");  // 返回 string
identity<number>(42);       // 返回 number

// 泛型接口:React Props 的典型模式
interface ApiResponse<T> {
    data: T;
    status: number;
    message: string;
}

// 实际使用
const response: ApiResponse<User[]> = {
    data: [{ name: "Alice", age: 25 }],
    status: 200,
    message: "success",
};

思考: 为什么 React 组件的 Props 要用泛型?泛型如何让组件在复用时代码类型安全?

5. TS + React 实战示例

// 定义 Props 接口
interface CounterProps {
    initialCount?: number;
    step?: number;
    onCountChange?: (count: number) => void;
}

// 带泛型的 API 响应组件
interface DataResponse<T> {
    data: T | null;
    loading: boolean;
    error: string | null;
}

// 组件实现
const Counter: React.FC<CounterProps> = ({
    initialCount = 0,
    step = 1,
    onCountChange,
}) => {
    const [count, setCount] = useState(initialCount);

    const increment = () => {
        const newCount = count + step;
        setCount(newCount);
        onCountChange?.(newCount);
    };

    return (
        <div>
            <span>Count: {count}</span>
            <button onClick={increment}>+{step}</button>
        </div>
    );
};

关联笔记