TypeScript 核心语法:给 JS 加上类型
TypeScript 就是 JavaScript + 类型系统。搞懂类型标注、Interface、泛型,日常开发就够用了。
从零搭建 Next.js 博客
- 1前端工具链入门:npm、pnpm、npx 是什么
- 2JavaScript 核心语法速览
- 3TypeScript 核心语法:给 JS 加上类型
- 4React 组件基础:JSX、Props、导入导出
- 5Next.js App Router 核心特性
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 会显示推断出的类型。