类型编程
品牌类型与标称类型
品牌类型模拟标称类型、Flavor 类型、防止 ID 混淆
品牌类型与标称类型
TypeScript 是结构类型系统——两个形状相同的类型被视为"相同"。品牌类型(Branded Types)模拟标称类型,防止 ID 混淆。
学完本章你将: 掌握品牌类型、Flavor 类型、防止 ID 混淆。
问题:结构类型带来的混淆
typescript
type UserId = number;
type OrderId = number;
function getUser(id: UserId) { }
function getOrder(id: OrderId) { }
const uid: UserId = 1;
getOrder(uid); // ✅ 编译通过!但逻辑上 UserId 不应该传给 getOrder
解决:品牌类型
typescript
// 给类型打上"品牌"标记(编译时存在,运行时消失)
type Brand<T, B> = T & { __brand: B };
type UserId = Brand<number, "UserId">;
type OrderId = Brand<number, "OrderId">;
function getUser(id: UserId) { }
function getOrder(id: OrderId) { }
const uid = 1 as UserId;
// getOrder(uid); // ❌ 类型错误!完美
工厂函数创建品牌类型
typescript
function createUserId(id: number): UserId {
return id as UserId; // 唯一的"不安全"转换点
}
// 使用——无法意外混淆
const uid = createUserId(42);
getUser(uid); // ✅
// getOrder(uid); // ❌
Flavor 类型(轻量版)
typescript
// Flavor 不强制类型转换,只是一个"提示"
type Flavor<T, F> = T & { __flavor?: F };
type Email = Flavor<string, "Email">;
type Username = Flavor<string, "Username">;
// 可以互相赋值(因为是 string),但 IDE 会提示