TypeScript 入门指南:为什么你的下一个项目应该用 TS

TypeScript 入门指南:为什么你的下一个项目应该用 TS

如果你还在犹豫要不要学 TypeScript,我的建议是:立刻开始。

JavaScript 本身没有类型系统,大型项目里一个 undefined is not a function 就能让你排查半天。TypeScript 在 JS 基础上加了静态类型,让 bug 在编译阶段就被发现。


为什么选择 TypeScript

javascript
// JavaScript:运行时才能发现问题
function greet(name) {
  return "Hello, " + name.toUpperCase();
}
greet(42); // TypeError: name.toUpperCase is not a function

typescript
// TypeScript:编译时就报错
function greet(name: string) {
  return "Hello, " + name.toUpperCase();
}
greet(42); // ❌ 类型错误:number 不能赋值给 string

核心优势


  • 编译期类型检查,减少运行时错误

  • IDE 智能提示更强大(自动补全、重构)

  • 代码自文档化,降低维护成本

  • 团队协作时接口清晰
  • 快速上手

    bash
    # 全局安装
    npm install -g typescript
    
    # 初始化项目
    mkdir my-ts-project && cd my-ts-project
    tsc --init
    
    # 编译
    tsc index.ts

    基础类型

    typescript
    // 基本类型
    let name: string = "TypeScript";
    let age: number = 10;
    let isAwesome: boolean = true;
    let data: any = "可以是任何类型";  // 尽量少用
    let nothing: void = undefined;
    
    // 数组
    let fruits: string[] = ["apple", "banana"];
    let numbers: Array<number> = [1, 2, 3];
    
    // 对象
    let user: { name: string; age: number } = {
      name: "Alice",
      age: 30
    };

    接口与类型

    typescript
    // 定义接口
    interface User {
      id: number;
      name: string;
      email: string;
      createdAt: Date;
    }
    
    // 类型别名
    type Status = "active" | "inactive" | "banned";
    type Point = { x: number; y: number };
    
    // 使用
    function createUser(data: Omit<User, "id" | "createdAt">): User {
      return {
        id: Date.now(),
        ...data,
        createdAt: new Date()
      };
    }
    
    // 泛型
    function getFirst<T>(arr: T[]): T | undefined {
      return arr[0];
    }
    
    const firstUser = getFirst<User>(users);

    实用工具类型

    typescript
    interface Todo {
      title: string;
      description: string;
      completed: boolean;
      createdAt: Date;
    }
    
    // 部分属性可选
    type PartialTodo = Partial<Todo>;
    
    // 只读
    type ReadonlyTodo = Readonly<Todo>;
    
    // 选取部分属性
    type TodoPreview = Pick<Todo, "title" | "completed">;
    
    // 排除属性
    type TodoWithoutMeta = Omit<Todo, "createdAt">;
    
    // 记录类型
    type PageInfo = Record<string, string | number>;

    函数类型

    typescript
    // 函数声明
    function add(a: number, b: number): number {
      return a + b;
    }
    
    // 箭头函数
    const multiply = (a: number, b: number): number => a * b;
    
    // 可选参数
    function greet(name: string, greeting?: string): string {
      return `${greeting || "Hello"}, ${name}!`;
    }
    
    // 重载
    function process(value: string): string[];
    function process(value: number): number[];
    function process(value: string | number): string[] | number[] {
      if (typeof value === "string") {
        return value.split("");
      }
      return [value];
    }

    类与面向对象

    typescript
    class Animal {
      constructor(public name: string, private age: number) {}
      
      protected getInfo(): string {
        return `${this.name} is ${this.age} years old`;
      }
    }
    
    class Dog extends Animal {
      constructor(name: string, age: number, public breed: string) {
        super(name, age);
      }
      
      bark(): string {
        return `${this.name} says woof!`;
      }
    }

    tsconfig.json 配置

    json
    {
      "compilerOptions": {
        "target": "ES2022",
        "module": "ESNext",
        "strict": true,
        "outDir": "./dist",
        "rootDir": "./src",
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true,
        "declaration": true,
        "sourceMap": true
      },
      "include": ["src/**/*"],
      "exclude": ["node_modules", "dist"]
    }

    与 React 结合

    typescript
    import React, { useState, useEffect } from 'react';
    
    interface Props {
      userId: number;
    }
    
    interface UserData {
      name: string;
      email: string;
    }
    
    const UserProfile: React.FC<Props> = ({ userId }) => {
      const [user, setUser] = useState<UserData | null>(null);
      const [loading, setLoading] = useState(true);
    
      useEffect(() => {
        fetch(`/api/users/${userId}`)
          .then(res => res.json())
          .then((data: UserData) => {
            setUser(data);
            setLoading(false);
          });
      }, [userId]);
    
      if (loading) return <div>加载中...</div>;
      return <div>{user?.name} ({user?.email})</div>;
    };

    最佳实践


  • 开启 strict 模式,不要为了省事用 any

  • 优先用 interface 定义对象结构,用 type 定义联合类型

  • 泛型能写就别用 any

  • 使用 as const 保持字面量类型

  • unknown 替代 any 处理不确定的类型

  • 善用 satisfies 关键字保持类型推断

  • TypeScript 的学习曲线很平缓 —— 你可以从给函数加类型开始,逐步深入。一旦用上就回不去了。

    推荐指数:⭐⭐⭐⭐⭐

    官方文档:https://www.typescriptlang.org/docs/

    💬 评论区 (0)

    暂无评论,快来抢沙发吧!