那些藏在Claude Code源码里的 TypeScript 高级技巧
一、TypeScript 背景与概述
二、基本知识 vs 高级知识
基本知识
-
基础类型与注解、`interface` / `type`、可选与只读
-
函数与类、泛型函数
-
模块:`import` / `export`、`import type` 与值导入分离
-
联合类型与收窄、`switch`
-
`tsconfig`:`strict`、`moduleResolution`、ESM 与 `.js` 扩展名等团队约定
高级知识(大型项目与 SDK 集成中常见)
|
主题 |
要点 |
|---|---|
|
可辨识联合 |
用 `type` 字段区分形态,`switch` + `never` 做穷尽检查 |
|
类型守卫 |
`function isFoo(x: unknown): x is Foo`,处理 JSON/IPC |
|
断言签名 |
`asserts x is T`:校验失败抛错,成功后收窄类型 |
|
Branded types |
`string & { __brand: ‘Id’ }`,区分同构不同义的字符串 |
|
`satisfies` |
对象满足某类型,又保留字面量信息 |
|
`const` 断言 |
`as const` 固定字面量类型,配合 `(typeof arr)[number]` |
|
工具类型与推断 |
`ReturnType`、`Awaited`、`infer`(含从 `Map` 等推断) |
|
Zod |
`z.infer<typeof schema>`,运行时校验与 TS 类型同源 |
|
`: never` 返回 |
表示不返回(退出进程等),辅助控制流分析 |
三、Claude Code 源码中的 TypeScript 实战与技巧
1. Branded types:SessionId / AgentId
// types/ids.tsexport type SessionId = string & { readonly __brand: 'SessionId' }export type AgentId = string & { readonly __brand: 'AgentId' }
2. `satisfies` 注册命令
// commands/help/index.tsconst help = {type: 'local-jsx',name: 'help',description: 'Show help and available commands',load: () => import('./help.js'),} satisfies Command
3. 类型谓词收窄 `unknown`(Bridge 消息)
// bridge/bridgeMessaging.tsexport function isSDKMessage(value: unknown): value is SDKMessage {return (value !== null &&typeof value === 'object' &&'type' in value &&typeof value.type === 'string')}
4. `asserts` 收窄参数
// services/plugins/pluginOperations.tsexport function assertInstallableScope(scope: string,): asserts scope is InstallableScope {if (!VALID_INSTALLABLE_SCOPES.includes(scope as InstallableScope)) {throw new Error(/* ... */)}}
5. `switch` 穷尽:`never`
// commands.ts(meetsAvailabilityRequirement 内 switch)default: {const _exhaustive: never = avoid _exhaustivebreak}
6. CLI 退出:`: never`
// cli/exit.tsexport function cliError(msg?: string): never {if (msg) console.error(msg)process.exit(1)return undefined as never}
7. Zod + `z.infer` + 懒加载 schema
// types/hooks.tsexport const promptRequestSchema = lazySchema(() => z.object({ /* ... */ }))export type PromptRequest = z.infer<ReturnType<typeof promptRequestSchema>>
8. 从 `Map` 推断值类型
// utils/conversationRecovery.ts(loadMessagesFromJsonlPath)let tip: (typeof byUuid extends Map<UUID, infer T> ? T : never) | null = null
9. 工具函数:泛型与 `readonly`
// utils/array.tsexport function count<T>(arr: readonly T[], pred: (x: T) => unknown): number { /* ... */ }
10. 条件 `require` 与 `typeof import()`
// query.ts(feature 开关 + 条件 require)const reactiveCompact = feature('REACTIVE_COMPACT')? (require('./services/compact/reactiveCompact.js') as typeof import('./services/compact/reactiveCompact.js')): null
夜雨聆风