TypeScript 基础知识
·
一、什么是 TypeScript
TypeScript(简称 TS)是 JavaScript 的超集,在 JS 的基础上添加了静态类型检查。TS 代码最终会被编译成普通 JS 代码在浏览器或 Node.js 中运行。
# 安装 TypeScript 编译器
npm install -g typescript
# 编译 TS 文件为 JS
tsc hello.ts
// tsconfig.json — 项目配置文件,用 tsc --init 生成(支持注释)
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"outDir": "./dist"
},
"include": ["src/**/*"]
}
二、基础类型
2.1 原始类型
let name: string = "张三";
let age: number = 25;
let isStudent: boolean = true;
let empty: null = null;
let notDefined: undefined = undefined;
// bigint 和 symbol
let big: bigint = 100n;
let sym: symbol = Symbol("id");
2.2 数组与元组
// 数组
let list: number[] = [1, 2, 3];
let list2: Array<string> = ["a", "b"];
// 元组 — 固定长度和类型的数组
let person: [string, number] = ["张三", 25];
// person[0] 是 string,person[1] 是 number
2.3 特殊类型
// any — 跳过类型检查(尽量避免使用)
let data: any = "hello";
data = 42; // 不报错
// unknown — 安全版的 any,使用前必须进行类型检查
let input: unknown = "hello";
// console.log(input.toUpperCase()); // 报错!
if (typeof input === "string") {
console.log(input.toUpperCase()); // 正确
}
// void — 无返回值
function log(msg: string): void {
console.log(msg);
}
// never — 永远不会有返回值
function throwError(msg: string): never {
throw new Error(msg);
}
// 字面量类型 — 限定为某个具体值
let direction: "left" | "right" | "up" | "down" = "left";
let level: 1 | 2 | 3 = 2;
三、对象类型
3.1 接口(interface)
interface User {
name: string;
age: number;
readonly id: number; // 只读属性
email?: string; // 可选属性
}
const user: User = {
name: "张三",
age: 25,
id: 1,
};
// user.id = 2; // 报错,readonly 不允许修改
3.2 类型别名(type)
type ID = string | number;
type Point = {
x: number;
y: number;
};
// 联合类型
type Status = "active" | "inactive" | "pending";
// 交叉类型
type Person = { name: string };
type Employee = { company: string };
type Worker = Person & Employee;
// Worker 包含 name 和 company
3.3 interface vs type
| 特性 | interface | type |
|---|---|---|
| 扩展 | extends |
& 交叉 |
| 声明合并 | 支持 | 不支持 |
| 基本类型别名 | 不支持 | 支持 |
| 适用场景 | 定义对象形状 | 联合、交叉、工具类型 |
// interface 继承
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
四、函数
4.1 函数类型定义
// 普通函数
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 ? `${greeting}, ${name}` : `Hello, ${name}`;
}
// 默认参数
function createUser(name: string, role: string = "user") {
return { name, role };
}
// 剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((total, n) => total + n, 0);
}
4.2 函数类型表达式
type MathFn = (a: number, b: number) => number;
const subtract: MathFn = (a, b) => a - b;
// 用接口定义函数
interface SearchFunc {
(source: string, sub: string): boolean;
}
const contains: SearchFunc = (src, sub) => src.includes(sub);
五、联合类型与类型守卫
5.1 联合类型
function printId(id: number | string) {
console.log(`ID: ${id}`);
}
5.2 类型守卫 — 缩小类型范围
// typeof 守卫
function double(value: number | string) {
if (typeof value === "number") {
return value * 2; // 此处 value 确定为 number
}
return value.repeat(2); // 此处 value 确定为 string
}
// instanceof 守卫
function getDate(value: Date | string): string {
if (value instanceof Date) {
return value.toISOString();
}
return value;
}
// 字面量类型守卫
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rect"; width: number; height: number };
function getArea(shape: Shape): number {
if (shape.kind === "circle") {
return Math.PI * shape.radius ** 2;
}
return shape.width * shape.height;
}
六、泛型(Generics)
泛型让函数、类型可以处理多种类型,同时保持类型安全。
6.1 基本用法
// 泛型函数
function identity<T>(arg: T): T {
return arg;
}
const result1 = identity<string>("hello"); // 类型为 string
const result2 = identity(42); // 自动推断为 number
6.2 常见场景
// 泛型接口
interface Box<T> {
value: T;
}
const stringBox: Box<string> = { value: "hello" };
const numberBox: Box<number> = { value: 42 };
// 泛型约束
interface HasLength {
length: number;
}
function getLength<T extends HasLength>(arg: T): number {
return arg.length;
}
getLength("hello"); // 正确,string 有 length
getLength([1, 2, 3]); // 正确,数组有 length
// getLength(42); // 报错,number 没有 length
// 注意:以下工具类型(Partial、Required 等)都是 TypeScript 内置的,无需自己定义。
// 这里展示它们的底层实现原理,帮助你理解映射类型的写法:
// type Partial<T> = { [K in keyof T]?: T[K] };
// type Required<T> = { [K in keyof T]-?: T[K] };
// type Pick<T, K> = { [P in K]: T[P] };
// type Readonly<T> = { readonly [K in keyof T]: T[K] };
// type Record<K, T> = { [P in K]: T };
6.3 实际示例
// 通用 API 响应类型
interface ApiResponse<T> {
code: number;
message: string;
data: T;
}
interface User {
id: number;
name: string;
}
// 使用时 data 自动推导为 User[]
async function getUsers(): Promise<ApiResponse<User[]>> {
const res = await fetch("/api/users");
return res.json();
}
七、类(Class)
7.1 基本定义
class Person {
// 属性声明(TS 要求先声明再使用)
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): string {
return `我是 ${this.name},今年 ${this.age} 岁`;
}
}
const p = new Person("张三", 25);
7.2 修饰符
class Animal {
// public — 默认,随处可访问
public name: string;
// private — 仅类内部可访问
private _age: number;
// protected — 类内部及子类可访问
protected type: string;
// readonly — 只能在构造函数中赋值
readonly id: number;
constructor(name: string, age: number, type: string, id: number) {
this.name = name;
this._age = age;
this.type = type;
this.id = id;
}
}
7.3 简写形式(参数属性)
class Student {
constructor(
public name: string,
private age: number,
readonly id: number
) {}
}
// 等同于手动声明 + constructor 赋值
7.4 抽象类
abstract class Shape {
abstract getArea(): number; // 子类必须实现
describe(): string {
return `面积: ${this.getArea().toFixed(2)}`;
}
}
class Circle extends Shape {
constructor(public radius: number) {
super();
}
getArea(): number {
return Math.PI * this.radius ** 2;
}
}
7.5 实现接口
interface Printable {
print(): void;
}
class Document implements Printable {
constructor(public content: string) {}
print(): void {
console.log(this.content);
}
}
八、枚举(Enum)
// 数字枚举(默认从 0 开始)
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right, // 3
}
// 字符串枚举
enum Role {
Admin = "ADMIN",
User = "USER",
Guest = "GUEST",
}
// 使用
let dir: Direction = Direction.Up;
if (dir === Direction.Up) {
// ...
}
提示:优先使用联合字面量类型代替枚举,更轻量:
type Direction = "up" | "down" | "left" | "right";
九、类型断言
类型断言告诉编译器"我比你更了解这个类型",不会进行运行时检查。
// as 语法(推荐)
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
// 尖括号语法(JSX 中不可用)
const input = <HTMLInputElement>document.getElementById("input");
// 非空断言 — 告诉编译器值不是 null/undefined
const el = document.querySelector(".box")!; // 断言元素一定存在
// 双重断言(极不推荐,通常意味着设计有问题)
const value = "hello" as unknown as number;
十、模块与命名空间
10.1 模块
每个包含 import 或 export 的文件都是一个模块。
// utils.ts — 导出
export function add(a: number, b: number): number {
return a + b;
}
export const PI = 3.14;
// 默认导出
export default class Calculator {}
// main.ts — 导入
import Calculator from "./utils";
import { add, PI } from "./utils";
// 全部导入
import * as utils from "./utils";
10.2 类型导入(type-only import)
// 仅导入类型,编译后会被移除
import type { User } from "./types";
import { type User, formatName } from "./utils";
十一、实用工具类型
TypeScript 内置了许多实用类型,定义在 lib.es5.d.ts 中。
interface Todo {
title: string;
description: string;
completed: boolean;
}
// Partial — 所有属性变可选
type PartialTodo = Partial<Todo>;
// { title?: string; description?: string; completed?: boolean }
// Required — 所有属性变必填
type RequiredTodo = Required<PartialTodo>;
// Pick — 选取部分属性
type TodoPreview = Pick<Todo, "title" | "completed">;
// { title: string; completed: boolean }
// Omit — 排除部分属性
type TodoInfo = Omit<Todo, "completed">;
// { title: string; description: string }
// Record — 构造键值对类型
type PageInfo = Record<string, { title: string }>;
// { [url: string]: { title: string } }
// Readonly — 所有属性只读
type ReadonlyTodo = Readonly<Todo>;
// ReturnType — 获取函数返回值类型
function createUser() {
return { name: "张三", age: 25 };
}
type User = ReturnType<typeof createUser>;
// keyof — 获取对象所有键的联合类型
type TodoKeys = keyof Todo; // "title" | "description" | "completed"
十二、声明文件(.d.ts)
用于描述已有 JavaScript 库的类型。
// global.d.ts — 全局类型声明
declare function formatDate(date: Date): string;
declare namespace MyLib {
function greet(name: string): string;
const version: string;
}
// 使用第三方库的类型包
// npm install @types/lodash
import _ from "lodash";
十三、配置要点
tsconfig.json 常用配置:
{
"compilerOptions": {
"target": "ES2020", // 编译目标
"module": "ESNext", // 模块系统
"strict": true, // 开启所有严格检查(推荐)
"noImplicitAny": true, // 禁止隐式 any
"strictNullChecks": true, // 严格空值检查
"noUnusedLocals": true, // 未使用变量报错
"moduleResolution": "node", // 模块解析策略
"esModuleInterop": true, // 兼容 CommonJS 模块
"outDir": "./dist", // 输出目录
"sourceMap": true // 生成 sourcemap
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
十四、学习建议
- 先学 JS 再学 TS — TS 是 JS 的超集,JS 基础是前提
- 开启
strict: true— 从一开始就养成严格类型的习惯 - 少用
any,多用unknown—any会绕过所有类型检查 - 优先用
type— 大多数场景下type和interface互换,type更灵活 - 善用编辑器提示 — VS Code 的 TS 支持非常强大,悬停查看类型,错误提示很详细
- 渐进式迁移 — 如果现有 JS 项目迁移,可以逐步将
.js改为.ts,允许any过渡
更多推荐


所有评论(0)