TypeScript 強力組合:斷言(Assertion)+ 品牌類型(Branded Types)

曾經一直在為“既要類型嚴密,又要代碼靈活”而頭疼。基礎類型和泛型固然強大,但真實世界的應用更復雜:你需要能優雅處理復雜度的模式與范式。
今天來看看幾種“上手即爽”的 TypeScript 進階技巧,幫你寫出夠硬、夠順手的 TS 應用。
下面這些技巧成了我的常用套路——一起來拆解。
Branded Types(品牌類型)
我常把字符串搞混:比如ID和郵箱混為一談。品牌類型就是給值“打標簽”,把看似同構的原始類型區分開。
type Password = string & { __brand: 'password' };
function setPassword(password: Password) {}
const raw = 'secret123';
setPassword(raw); // ? 報錯
setPassword(raw as Password); // ? 通過type Email = string & { __brand: 'email' };
type Username = string & { __brand: 'username' };
function createEmail(value: string): Email {
if (!value.includes('@')) throw new Error('Invalid email');
return value as Email;
}
function sendMessage(to: Email) {
console.log(`Sending to ${to}`);
}
const email = createEmail('user@domain.com');
sendMessage(email); // ? 通過
sendMessage('not-an-email'); // ? 報錯這樣就有了清晰邊界:在入口處做一次校驗,之后到處都能信任這個類型。
Assertion Functions(斷言函數)
它們是我的運行時校驗秘笈。不僅是類型守衛(type guard),更是告訴 TS “相信我”。在復雜校驗邏輯中尤其好用。
示例:
function assertIsString(value: unknown): asserts value is string {
if (typeof value !== 'string') throw new Error('Not a string');
}
function processInput(input: unknown) {
assertIsString(input);
console.log(input.toUpperCase()); // ? TS 現在知道 input 是 string 了
}
processInput('Amit'); // ? 成功
processInput(123); // ? 拋錯凡是你需要“類型把關 + 失敗就中斷”的地方,都可以用斷言函數。
類型謂詞 與 斷言函數
在 TS 里“收窄類型”有時像猜謎。類型謂詞(value is Type)和斷言函數讓它精確可控。
斷言函數更進一步:拋錯來強制類型成立。兩者配合,會顯著提升 TS 的收窄表現,是復雜分支里的好隊友。
interface User {
name: string;
}
function isUser(value: unknown): value is User {
return typeof value === 'object' && value !== null && 'name' in value;
}
function greet(value: unknown) {
if (isUser(value)) {
console.log(`Hello, ${value.name}`);
}
}
greet('Amit'); // (不輸出)
greet({ name: 'Amit' }); // Hello, Amit類也能很優雅
不僅僅是 OOP 愛好者的玩具——它們非常適合構建器(builder)模式,還能配合斷言打造流式、類型安全的 API(例如 tRPC 的一些設計思路)。
class Client {
private user?: { id: string };
constructor(user?: { id: string }) {
this.user = user;
}
// 斷言:調用后,this 必須具備 { user: { id: string } }
assertLoggedIn(): asserts this is this & { user: { id: string } } {
if (!this.user) throw new Error('Not logged in');
}
}這樣可以在方法鏈中保證狀態,寫出既順滑又安全的接口。
總結
今天我們看了幾種實用的 TypeScript 模式:
- 品牌類型:給原始類型“打標簽”,一次校驗、處處可信;
- 斷言函數:運行時把關 + 編譯期收窄,復雜邏輯里的穩定器;
- 類型謂詞:與斷言互補,精準描述分支條件;
- 類 + 斷言:構建流式、類型安全的 API。
這些套路能讓你的代碼既健壯又靈活,減少 bug、降低重構壓力。






























