M
← 文章列表
·5 分钟阅读·1,253TypeScript学习笔记

TypeScript 核心语法:给 JS 加上类型

TypeScript 就是 JavaScript + 类型系统。搞懂类型标注、Interface、泛型,日常开发就够用了。

TypeScript 核心语法:给 JS 加上类型

TypeScript 是 JavaScript 的超集,在 JS 的基础上加了类型系统。所有合法的 JS 代码都是合法的 TS 代码,区别只是 TS 多了类型标注。

为什么要用 TypeScript?

  • IDE 自动补全,写 post. 会提示有哪些字段
  • 写错类型立刻报错,不用等到运行时才发现 bug
  • 代码即文档,看类型定义就知道数据长什么样

1. 基本类型标注

: 类型 的方式标注变量和函数的类型:

let name: string = "Mary";
let age: number = 25;
let isActive: boolean = true;
let tags: string[] = ["Next.js", "TypeScript"];

// 类型确定后,赋错类型会报错
name = 123;   // ❌ 不能把 number 赋给 string
name = "Bob"; // ✅

2. 类型推断

大多数情况下不需要手动写类型,TypeScript 能自动推断:

let name = "Mary"; // 推断为 string
let age = 25;      // 推断为 number
let tags = ["a"];  // 推断为 string[]

// 所以这两种写法效果一样:
let name: string = "Mary"; // 手动标注
let name = "Mary";         // 自动推断(推荐)

3. 函数类型

// 标注参数类型和返回值类型
function add(a: number, b: number): number {
  return a + b;
}

// 没有返回值用 void
function log(msg: string): void {
  console.log(msg);
}

// 可选参数加 ?
function greet(name: string, title?: string): string {
  return title ? title + name : name;
}

greet("Mary");         // ✅
greet("Mary", "Dr."); // ✅

4. Interface(接口)

描述一个对象的"形状",项目里用得最多:

interface Post {
  slug: string;
  title: string;
  date: string;
  tags: string[];
  coverImage?: string; // ? 表示可选字段
}

// 用这个类型
const post: Post = {
  slug: "hello-world",
  title: "你好世界",
  date: "2026-04-05",
  tags: ["Next.js"],
  // coverImage 可以不写,因为是可选的
};

post.title = 123; // ❌ 报错,title 必须是 string

5. Type 和 Interface 的区别

// interface:定义对象结构,可以继承扩展
interface Animal {
  name: string;
}
interface Dog extends Animal {
  breed: string;
}

// type:更灵活,可以定义联合类型
type ID = string | number;       // 联合类型:可以是 string 或 number
type Status = "draft" | "published" | "archived"; // 字面量联合类型

经验法则:

  • 定义对象结构 → 用 interface
  • 定义联合/交叉类型 → 用 type

6. 联合类型

// 可以是多种类型之一
let id: string | number;
id = "abc"; // ✅
id = 123;   // ✅
id = true;  // ❌

// 字面量联合:限定只能是几个固定值
type Level = "学习中" | "熟悉" | "掌握";
let level: Level = "学习中"; // ✅
let level: Level = "精通";   // ❌ 不在允许范围内

7. 泛型

让函数能处理多种类型,同时保留类型信息:

// 没有泛型:返回值类型变成了 any,类型信息丢失
function first(arr: any[]): any {
  return arr[0];
}

// 有泛型:T 是类型变量,调用时自动推断
function first<T>(arr: T[]): T {
  return arr[0];
}

const a = first([1, 2, 3]);   // T 推断为 number,a 是 number
const b = first(["x", "y"]); // T 推断为 string,b 是 string

8. 常用工具类型

// Record<K, V>:键是 K 类型、值是 V 类型的对象
const tagCounts: Record<string, number> = {
  "Next.js": 3,
  "TypeScript": 5,
};

// Promise<T>:异步函数返回的类型
async function getPost(): Promise<Post> {
  const post = await fetchPost();
  return post;
}

// Partial<T>:把所有字段变成可选
type PartialPost = Partial<Post>; // 所有字段都加上 ?

9. 特殊操作符

// ?. 可选链:左边是 null/undefined 时不报错,返回 undefined
const title = post?.title;

// ! 非空断言:告诉 TS "我确定不是 null/undefined",慎用
const title = post!.title;

// ?? 空值合并:左边是 null/undefined 时取右边的值
const tags = post.tags ?? [];

10. export 和 import

// 默认导出(一个文件只能有一个)
export default function PostCard() {}

// 导入时名字可以随便起
import PostCard from "./PostCard";
import Card from "./PostCard"; // 也合法

// 具名导出(可以有多个)
export function getAllPosts() {}
export function getAllTags() {}
export interface PostMeta {}

// 导入时必须用花括号,名字必须对得上
import { getAllPosts, getAllTags } from "./posts";

11. 类型守卫

联合类型需要在运行时判断具体是哪种类型,TypeScript 能根据判断"收窄"类型:

type Cat = { meow: () => void };
type Dog = { bark: () => void };
type Animal = Cat | Dog;

function makeSound(animal: Animal) {
  // 用 "in" 检查属性是否存在,TS 会自动收窄类型
  if ("meow" in animal) {
    animal.meow(); // 这里 TS 确定 animal 是 Cat
  } else {
    animal.bark(); // 这里 TS 确定 animal 是 Dog
  }
}

// 也可以用 typeof 收窄基本类型
function format(value: string | number) {
  if (typeof value === "string") {
    return value.toUpperCase(); // TS 确定是 string
  }
  return value.toFixed(2);     // TS 确定是 number
}

掌握这些,TypeScript 的日常开发就没什么障碍了。遇到看不懂的类型,把鼠标悬停在变量上,IDE 会显示推断出的类型。