plugins/languages/typescript/skills/types/SKILL.md
TypeScript 高级类型系统规范,覆盖 discriminated unions、模板字面量类型、条件 / mapped types、TS 5.5 inferred predicates 类型守卫、branded types、satisfies、Zod 4 / Valibot 运行时验证。同时给出 JS-only 项目通过 JSDoc + tsc --checkJs 获得类型保护的方案。Use when 设计复杂类型、类型体操、API 类型契约、运行时校验、JS 项目加类型保护,或用户提到 "类型系统"、"discriminated union"、"Zod schema"、"类型守卫"、"branded type"、"JSDoc 类型"。
npx skillsauth add lazygophers/ccplugin typescript-typesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
本 skill 同时覆盖 JavaScript 项目;JS 项目用 JSDoc + tsc --checkJs 获得 80% 类型保护,见末尾兜底章节。
类型系统两大用途:建模业务状态 (discriminated unions / branded types) + 验证外部输入 (Zod / Valibot)。
type UserDTO = { id: string; name: string }; // PascalCase
type ApiResponse<T> = { data: T; status: number };
type Status = "active" | "inactive" | "pending";
// 禁止 I 前缀
// type IUser = {};
type AsyncState<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; error: Error };
function render<T>(state: AsyncState<T>): string {
switch (state.status) {
case "idle": return "Waiting...";
case "loading": return "Loading...";
case "success": return `Got: ${JSON.stringify(state.data)}`;
case "error": return `Error: ${state.error.message}`;
default: {
const _exhaustive: never = state; // 穷举检查
return _exhaustive;
}
}
}
function createConfig<const T extends Record<string, unknown>>(c: T): T {
return c;
}
const cfg = createConfig({ api: "/v1", timeout: 3000 });
// typeof cfg = { readonly api: "/v1"; readonly timeout: 3000 }
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIRoute = `/api/${string}`;
type Endpoint = `${HTTPMethod} ${APIRoute}`;
type EventName = `on${Capitalize<string>}`;
// TS 5.5+: 推断类型谓词
function isNonNullable<T>(v: T): v is NonNullable<T> {
return v !== null && v !== undefined;
}
const users: (User | null)[] = [u1, null, u2];
const valid = users.filter(isNonNullable); // User[]
// 显式自定义类型守卫
function isUser(v: unknown): v is User {
return typeof v === "object" && v !== null
&& "id" in v && typeof (v as { id: unknown }).id === "string";
}
import { z } from "zod";
const UserSchema = z.object({
id: z.uuid(), // Zod 4: 顶层 helper
name: z.string().min(1).max(100),
email: z.email(),
role: z.enum(["admin", "user", "guest"]),
metadata: z.record(z.string(), z.unknown()).optional(),
});
type User = z.infer<typeof UserSchema>; // schema-first 类型
const r = UserSchema.safeParse(data);
if (!r.success) console.error(z.treeifyError(r.error));
// 派生 schema
const CreateUserSchema = UserSchema.omit({ id: true }).extend({
password: z.string().min(8).regex(/[A-Z]/).regex(/[0-9]/),
});
替代选择:Valibot (更小 bundle,函数式 API,<2KB),用于体积敏感场景。
type Brand<T, B extends string> = T & { readonly __brand: B };
type UserId = Brand<string, "UserId">;
type PostId = Brand<string, "PostId">;
function getUser(id: UserId): Promise<User> { /* ... */ }
// getUser("123" as UserId); // OK
// getUser("123" as PostId); // Error
const routes = {
home: "/",
about: "/about",
user: "/user/:id",
} satisfies Record<string, string>;
// typeof routes.home = "/" (非 string)
// 内置:Partial / Required / Pick / Omit / Record / Readonly / Awaited / ReturnType / Parameters
// type-fest 推荐补充:SetOptional, SetRequired, Merge, CamelCase, etc.
type ExtractPromise<T> = T extends Promise<infer U> ? U : T;
type DeepReadonly<T> = { readonly [K in keyof T]: DeepReadonly<T[K]> };
JS 项目无需切 TS 也能获得 80% 类型保护:
// jsconfig.json
{
"compilerOptions": {
"target": "ES2025",
"module": "NodeNext",
"allowJs": true,
"checkJs": true,
"strict": true,
"noEmit": true
},
"include": ["src/**/*"]
}
// JSDoc 类型定义
/**
* @typedef {Object} User
* @property {string} id
* @property {string} name
* @property {'admin' | 'user' | 'guest'} role
*/
/** @typedef {{ status: 'idle' } | { status: 'loading' } | { status: 'success'; data: User } | { status: 'error'; error: Error }} AsyncState */
/**
* @param {string} id
* @returns {Promise<User>}
*/
export async function getUser(id) {
const r = await fetch(`/api/users/${id}`);
return /** @type {User} */ (await r.json());
}
// Zod 在 JS 同样可用,z.infer 通过 JSDoc 桥接
import { z } from 'zod';
const UserSchema = z.object({ id: z.uuid(), name: z.string() });
/** @typedef {z.infer<typeof UserSchema>} User */
pnpm tsc --noEmit # 当 linter 跑
渐进迁移:JSDoc → 文件级 .ts → 局部启 strict → 全量 strict。
| 现象 | 问题 | 严重 |
|------|------|------|
| any | 用 unknown + 守卫 | 高 |
| 未穷举的 switch | DU 遗漏分支 | 高 |
| as 强转 | 可能隐藏错误 (仅边界用) | 中 |
| 外部数据无 Zod | 运行时类型不安全 | 高 |
| 递归类型 > 5 层 | 编译性能 | 中 |
| I 前缀 | C# 约定 | 低 |
| enum | tree-shake 不友好 | 中 |
| JS 项目无 checkJs | 失去类型保护 | 中 |
any,外部数据 Zod / Valibot 验证never 穷举import type 分离类型 (TS)extends 约束satisfiesI 前缀checkJs: true + JSDoctools
UI/UX 与布局设计——做界面布局/结构/导航/组件/交互的设计决策。触发:做UI/UX/布局/排版/导航/组件/交互/栅格/响应式/图表选型/字体配对。按媒介路由 HTML/Web、原生 App(iOS/Android/桌面)、CLI、TUI。需后端动态系统不适用;配色/主题/色板走姊妹 skill design-color。
tools
主题与配色设计——做颜色搭配/调色板/主题/品牌色阶/暗模式的设计决策。触发:选配色/调色/主题/色板/品牌色/暗模式/对比度/色盲/UI风格。按媒介路由 HTML/Web(CSS变量)、原生App(平台token)、CLI(ANSI)、TUI(真彩/256/16降级)。保证可访问性(对比度/色盲安全)。需后端动态系统不适用;UI/UX 布局/组件/交互走姊妹 skill design-uiux。
tools
跨任意组件(plugin/skill/agent/command)的验证驱动优化循环纪律 skill。当用户要优化某个已有组件却无明确方向、或要防止改了反而更差(自评乐观偏差 / 多维同改归因失效 / 为凑分加废话膨胀)、或要把一套通用「评分→单变量改→改后验证严格更好才留否则回滚→触顶停」的纪律套到任意组件上时使用。管优化过程本身的纪律(validation gate / ratchet / 独立验证 / 触顶停),不评单组件深度(交 skill-dev),不查插件接线(交 plugin-dev)。仅手动 /optimize-any 触发。
data-ai
两层规则记忆 (基于 .skein/spec)。planning 时 recall 召回相关规则、task finish 后 sediment 沉淀学习 + prune 自动精简过期/重复/断链规则。core 常驻硬规 + recall 按需召回, 经判定门自动写盘 (不逐次问用户)。产出 .skein/spec 下 core/recall 规则文件 + index。另支持空仓 bootstrap 播种规则基线、记忆大面积失效 (大重构/换栈) 时 reconstruct 可逆归档后按项目类型分型重建、maintain 手动体检 (超预算/stale/断链/重复/废弃, --apply 自动修复)、auto-fix (Stop hook 写 .pending-fix 标记 → main 派 skein-specer bg 跑 maintain --apply 全自动修, 断链只报告)。