TypeScript 作为 JavaScript 的超集,其核心价值在于为动态类型的 JS 引入了静态类型系统。这套类型体系在编译阶段进行严格校验,但在运行时会被完全擦除,不会产生任何性能开销。这种设计既保留了 JS 的灵活性,又通过编译时的类型检查大幅提升了代码的健壮性。
我在实际项目中发现,一个完善的 TS 类型系统能够减少至少 30% 的运行时错误。特别是在大型项目中,当函数调用链路复杂、多人协作开发时,类型系统就像一套精密的"防错机制",能在编码阶段就发现潜在的类型问题。
TS 的类型体系可以划分为四个层次:
TypeScript 完整保留了 JavaScript 的七种原始数据类型,并新增了 void 类型:
typescript复制// 1. number - 所有数字类型,包括整数、浮点数、NaN、Infinity
let price: number = 99.99;
let quantity: number = 10;
// 2. string - 文本类型,支持模板字符串
let productName: string = "TypeScript Handbook";
let description: string = `This ${productName} costs $${price}`;
// 3. boolean - 仅 true/false
let isAvailable: boolean = true;
// 4. null - 表示空值
let emptyValue: null = null;
// 5. undefined - 表示未定义
let notDefined: undefined = undefined;
// 6. symbol - 唯一标识符
const uniqueKey: symbol = Symbol("productId");
// 7. bigint - 大整数
const bigNumber: bigint = 9007199254740991n;
// 8. void - 表示无返回值
function logMessage(): void {
console.log("This function returns nothing");
}
注意:在严格模式(
strictNullChecks)下,null 和 undefined 只能赋值给 any 和它们各自的类型。关闭该选项时,它们可以作为所有类型的子类型。
TS 具备强大的类型推断能力,在大多数情况下可以自动推导出变量类型:
typescript复制// 自动推断为 number 类型
let count = 10;
// 自动推断为 string[]
const colors = ["red", "green", "blue"];
// 自动推断返回值为 number
function sum(a: number, b: number) {
return a + b;
}
在实际开发中,我建议:
any 是类型系统的逃生舱,但应该尽量避免使用:
typescript复制let unsafe: any = "dangerous";
unsafe = 123; // 合法
unsafe.method(); // 编译通过,但运行时可能报错
unknown 是类型安全的替代方案:
typescript复制let safe: unknown = "safe";
// safe.toUpperCase(); ❌ 错误:必须先进行类型检查
if (typeof safe === "string") {
safe.toUpperCase(); // ✅ 安全
}
经验法则:
never 表示永远不会发生的值:
typescript复制// 抛出异常的函数
function fail(message: string): never {
throw new Error(message);
}
// 无限循环
function infiniteLoop(): never {
while (true) {}
}
// 穷尽检查
type Shape = "circle" | "square";
function getArea(shape: Shape): number {
switch (shape) {
case "circle": return Math.PI * 2;
case "square": return 4;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
枚举提供了更好的常量组织方式:
typescript复制// 数字枚举
enum StatusCode {
Success = 200,
BadRequest = 400,
Unauthorized = 401
}
// 字符串枚举(推荐)
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
// 常量枚举(编译时会被内联)
const enum LogLevel {
Info,
Warning,
Error
}
元组固定了数组的长度和每个位置的类型:
typescript复制// 定义经纬度元组
type Coordinate = [number, number];
const location: Coordinate = [39.9042, 116.4074];
// 定义带标签的元组(TS 4.0+)
type HttpResponse = [status: number, data: string];
const response: HttpResponse = [200, "OK"];
两种等效的数组定义方式:
typescript复制// 简单数组
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];
// 只读数组
const readonlyArray: ReadonlyArray<number> = [1, 2, 3];
// readonlyArray.push(4); ❌ 错误
// 多维数组
let matrix: number[][] = [
[1, 2],
[3, 4]
];
三种定义对象类型的方式:
typescript复制// 1. 内联类型
const user: {
name: string;
age?: number // 可选属性
} = { name: "Alice" };
// 2. 接口
interface Person {
name: string;
greet(): string;
}
// 3. 类型别名
type Point = {
x: number;
y: number;
};
联合类型表示"或"关系:
typescript复制type ID = string | number;
function printId(id: ID) {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id.toFixed(2));
}
}
交叉类型表示"与"关系:
typescript复制type Named = { name: string };
type Aged = { age: number };
type Person = Named & Aged;
const person: Person = { name: "Bob", age: 30 };
类型别名可以给任何类型命名:
typescript复制type StringOrNumber = string | number;
type Callback<T> = (data: T) => void;
接口专门描述对象形状:
typescript复制interface Animal {
name: string;
makeSound(): void;
}
interface Dog extends Animal {
breed: string;
bark(): void;
}
泛型提供了类型参数化能力:
typescript复制// 泛型函数
function identity<T>(arg: T): T {
return arg;
}
// 泛型接口
interface Result<T> {
success: boolean;
data: T;
}
// 泛型类
class Container<T> {
constructor(public value: T) {}
}
TypeScript 提供了强大的类型操作能力:
typescript复制// 索引访问
type User = { name: string; age: number };
type UserName = User["name"]; // string
// keyof
type UserKeys = keyof User; // "name" | "age"
// 条件类型
type IsString<T> = T extends string ? true : false;
// 映射类型
type ReadonlyUser = {
readonly [K in keyof User]: User[K];
};
typescript复制// Partial - 所有属性变为可选
type PartialUser = Partial<User>;
// Required - 所有属性变为必选
type CompleteUser = Required<User>;
// Pick - 选择部分属性
type NameOnly = Pick<User, "name">;
// Omit - 排除部分属性
type WithoutAge = Omit<User, "age">;
// Record - 构建键值类型
type PageInfo = Record<"home" | "about", { title: string }>;
typescript复制// 自定义类型守卫
function isString(value: unknown): value is string {
return typeof value === "string";
}
// 类型断言
const element = document.getElementById("app") as HTMLElement;
// 非空断言
function validate(input?: string) {
console.log(input!.length); // 慎用
}
渐进式类型策略:
类型设计原则:
typescript复制// 不好的写法
interface OverlyBroad {
[key: string]: any;
}
// 好的写法
interface WellDefined {
id: string;
createdAt: Date;
updatedAt?: Date;
}
性能考量:
协作规范:
经过多个大型项目的实践验证,良好的类型系统设计可以将代码维护成本降低40%以上。特别是在重构时,类型系统能够提供可靠的安全网,让开发者有信心进行大规模代码修改。