← ClaudeAtlas

fec-typescript-type-safetylisted

Use when designing, implementing, or reviewing TypeScript type contracts, advanced generics, discriminated unions, type guards, API DTOs, component props, public utility types, or type-level regressions in frontend projects. Prefer code review for broad PR review; Chinese triggers include TypeScript 类型安全, 类型建模, 泛型, 判别联合, 类型收窄.
bovinphang/frontend-craft · ★ 14 · Web & Frontend · score 80
Install: claude install-skill bovinphang/frontend-craft
# TypeScript 类型安全 ## Purpose 为前端代码建立可演进的类型契约,减少 `any`、断言和运行时形状漂移。 ## Procedure ### 1. 先确定类型边界 把类型分为外部输入、领域模型、UI view model、组件 props、工具函数 API。不要让后端 DTO、表单模型和 UI 展示模型互相冒充。 ```ts interface UserDto { id: string; display_name: string; status: "ACTIVE" | "DISABLED"; } interface UserViewModel { id: string; displayName: string; status: "active" | "disabled"; } export function mapUserDto(dto: UserDto): UserViewModel { return { id: dto.id, displayName: dto.display_name, status: dto.status === "ACTIVE" ? "active" : "disabled", }; } ``` ### 2. 用 `unknown` 和收窄处理不可信数据 外部输入先校验再使用。不要用 `as` 让编译器闭嘴。 ```ts interface ApiErrorBody { message: string; } function isApiErrorBody(value: unknown): value is ApiErrorBody { return ( typeof value === "object" && value !== null && "message" in value && typeof value.message === "string" ); } export function getApiErrorMessage(value: unknown): string { return isApiErrorBody(value) ? value.message : "Unexpected error"; } ``` ### 3. 用判别联合表达状态机 异步状态、权限分支、支付状态等有限状态,用判别字段让新增分支在编译期暴露。 ```ts type Loadable<T> = | { state: "idle" } | { state: "loading" } | { state: "success"; data: T } | { state: "error"; error: Error }; function assertNever(value: never): never { throw new Error(`Unhandled state: ${JSON.stringify(value)}`); } export function renderUserState(user: Loadable<{ name: string }>): string { switch (user.state) { case "idle": return "Ready"; case "loading":