mcpField
T
typescript-ops

typescript-ops

github.com/0xdarkmatter开发7838 次安装2 周前更新
代码仓库

关于 typescript-ops

typescript-ops 是面向开发者的 TypeScript 技能,涵盖类型系统与生产实践。它结合速查内容和深入指南,并介绍 TypeScript 6、7 的采用注意事项。

主要功能

  1. 01类型收窄与工具类型参考
  2. 02泛型、条件类型和映射类型模式
  3. 03现代 TypeScript 功能指南
  4. 04TypeScript 6 和 7 迁移说明
  5. 05tsconfig 与严格模式指南
  6. 06使用 Zod 4 进行运行时验证

适用场景

  1. 01为联合类型值选择类型守卫
  2. 02设计可复用的泛型类型辅助项
  3. 03检查严格编译器配置
  4. 04评估迁移到 TypeScript 7

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/0xdarkmatter/claude-mods --skill typescript-ops

安装后在 Claude Code 中输入/typescript-ops确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
typescript-facts.json
references/
config-strict.md
ecosystem.md
generics-patterns.md
ts7-native-compiler.md
type-system.md
utility-types.md
scripts/
check-typescript-facts.py
tests/
run.sh

详细介绍

TypeScript 操作

全面介绍 TypeScript 技能,涵盖类型系统、泛型和生产环境模式。

截至 2026-08-08 验证的生态系统信息(TypeScript 7、Zod 4、Valibot 1)。

时效性检查: python scripts/check-typescript-facts.py --offline 会断言目录中标注版本的事实(TypeScript 主版本、zod、valibot)仍在正文中提及,且上方注明日期的时效性说明仍然存在;运行 --live 可确认每个软件包在 npm 上的主版本仍与文档所述一致。目录:assets/typescript-facts.json。

类型收窄决策树

How to narrow a type?
│
├─ Primitive type check
│  └─ typeof: typeof x === "string"
│
├─ Instance check
│  └─ instanceof: x instanceof Date
│
├─ Property existence
│  └─ in: "email" in user
│
├─ Discriminated union
│  └─ switch on literal field: switch (event.type)
│
├─ Null/undefined check
│  └─ Truthiness: if (x) or if (x != null)
│
├─ Custom logic
│  └─ Type predicate: function isUser(x: unknown): x is User
│
└─ Assertion (you know better than TS)
   └─ as: value as string (escape hatch, avoid when possible)
类型守卫示例
interface Dog { bark(): void; breed: string }
interface Cat { meow(): void; color: string }

function isDog(pet: Dog | Cat): pet is Dog {
    return "bark" in pet;
}

function handlePet(pet: Dog | Cat) {
    if (isDog(pet)) {
        pet.bark(); // TS knows it's Dog here
    } else {
        pet.meow(); // TS knows it's Cat here
    }
}
可辨识联合类型
type Result<T> =
    | { status: "success"; data: T }
    | { status: "error"; error: string }
    | { status: "loading" };

function handle<T>(result: Result<T>) {
    switch (result.status) {
        case "success": return result.data;     // data is available
        case "error":   throw new Error(result.error); // error is available
        case "loading": return null;
    }
    // Exhaustiveness check: result is `never` here
    const _exhaustive: never = result;
}

实用类型速查表

实用类型功能示例
Partial<T>所有属性均为可选Partial<User> 用于更新载荷
Required<T>所有属性均为必需Required<Config> 用于已验证的配置
Readonly<T>所有属性均为只读Readonly<State> 用于不可变状态
Pick<T, K>选取特定属性Pick<User, "id" | "name">
Omit<T, K>移除特定属性Omit<User, "password">
Record<K, V>键和值均有类型的对象Record<string, number>
Exclude<U, E>从联合类型中移除类型Exclude<Status, "deleted">
Extract<U, E>保留联合类型中的类型Extract<Event, { type: "click" }>
NonNullable<T>移除 null/undefinedNonNullable<string | null>
ReturnType<F>函数返回类型ReturnType<typeof fetchUser>
Parameters<F>将函数参数表示为元组Parameters<typeof createUser>
Awaited<T>解包 Promise 类型Awaited<Promise<User>> = User

泛型模式

受约束的泛型
// Basic constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}

// Multiple constraints
function merge<T extends object, U extends object>(a: T, b: U): T & U {
    return { ...a, ...b };
}

// Default generic type
type ApiResponse<T = unknown> = {
    data: T;
    status: number;
};
条件类型
// Basic conditional
type IsString<T> = T extends string ? true : false;

// infer keyword - extract inner type
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type UnwrapArray<T> = T extends (infer U)[] ? U : T;

// Distributive conditional (distributes over union)
type ToArray<T> = T extends any ? T[] : never;
// ToArray<string | number> = string[] | number[]

// Prevent distribution with wrapping
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;
// ToArrayNonDist<string | number> = (string | number)[]
映射类型
// Make all properties optional and nullable
type Nullable<T> = { [K in keyof T]: T[K] | null };

// Add prefix to keys
type Prefixed<T, P extends string> = {
    [K in keyof T as `${P}${Capitalize<string & K>}`]: T[K];
};
// Prefixed<{ name: string }, "get"> = { getName: string }

// Filter keys by value type
type StringKeys<T> = {
    [K in keyof T as T[K] extends string ? K : never]: T[K];
};

深入了解:加载 ./references/generics-patterns.md,了解高级类型级编程、递归类型和模板字面量类型。

现代语言特性(TypeScript 5.x → 6.0)

特性始于功能
satisfies 运算符4.9根据类型检查值,但不扩大其类型
标准(TC39)装饰器5.0无需 experimentalDecorators,即可在类/方法上使用 @decorator
const 类型参数5.0function f<const T>(x: T) 无需在调用处使用 as const,即可推断字面量类型
using 声明5.2显式资源管理(Symbol.dispose),退出作用域时自动清理
推断出的类型谓词5.5arr.filter(x => x !== null) 无需手写 x is T 守卫即可收窄类型
verbatimModuleSyntax5.0强制仅用于类型的导入使用 import type,取代 importsNotUsedAsValues
// const type parameters (5.0) - literal inference without as const
function routes<const T extends readonly string[]>(paths: T): T { return paths; }
const r = routes(["/home", "/about"]); // readonly ["/home", "/about"], not string[]

// using declarations (5.2) - deterministic cleanup
function readConfig() {
    using file = openFile("config.json"); // file[Symbol.dispose]() runs at scope exit
    return parse(file.contents);
}

// Inferred type predicates (5.5) - no manual guard needed
const names = ["a", null, "b"].filter(x => x !== null); // string[], not (string | null)[]
TypeScript 6.0(过渡版本)

TS 6.0 是基于 JavaScript 的编译器的最后一个版本。它旨在过渡到 TS 7 中原生(Go)编译器,因此主要变化是更严格、现代化的默认设置:

  • strict: true 为默认值 — 从未设置该选项的 tsconfig 现在会启用完整的严格检查
  • 默认值现代化:module: esnext、target: es2025;es2025 库提供 Temporal、Map.getOrInsert、RegExp.escape 的类型
  • 移除旧选项:moduleResolution: classic;module: amd/umd/system/none;最低 target 现在为 ES2015(es5 已弃用)
  • 互操作始终启用:无法再禁用 esModuleInterop / allowSyntheticDefaultImports
  • 新增 --stableTypeOrdering 标志,便于对比 6.0 → 7.0 迁移差异
TypeScript 7(当前主版本 — 原生编译器)

TS 7 是用 Go 重写的版本(之前名为 tsgo),自 2026-07-08 起在 npm 上稳定发布。 类型检查语义相同,类型检查速度提升约 8–16 倍——但该软件包仅提供 bin/tsc shim,不含 JavaScript 编译器 API:在 7.0.x 中,require('typescript') 会抛出 MODULE_NOT_FOUND(该 API 将在 7.1+ 中回归)。影响采用决策的因素:

  • 使用 TS 程序化 API(ts.createSourceFile、自定义 lint 脚本、codemod、typescript-eslint)的仓库工具必须不再依赖 AST、改用其他解析器,或固定使用别名
  • 对嵌入式语言进行类型检查的工具(vue-tsc、svelte-check、Astro、MDX)在移植到 7.1+ API 之前都固定使用 TS 6——这是选择技术栈时需要考虑的实际因素
  • 已使用 TS 6 的 tsconfig 可直接采用默认配置(可跳过 6.0 过渡版本); baseUrl 会导致硬错误(TS5102)
  • 在 7 旁边运行 typescript5 回退别名会导致裸调用 npx tsc 产生歧义——试运行期间,脚本必须使用明确的编译器路径

深入了解:加载 ./references/ts7-native-compiler.md,了解无 JS API 时的解决方法、 双重安装导致的 bin 歧义、生态系统无法采用情况表、实测采用基准(12.1 倍) 以及是否继续的检查清单。

tsconfig 快速参考

{
    "compilerOptions": {
        // Strict mode (default in TS 6; state it explicitly anyway)
        "strict": true,               // Enables all strict checks
        "noUncheckedIndexedAccess": true,  // arr[0] is T | undefined

        // Module system (TS 6 defaults to module: esnext; interop is always on)
        "module": "esnext",           // or "nodenext" for Node
        "moduleResolution": "bundler", // or "nodenext"

        // Output (TS 6 defaults target to es2025; min supported is es2015)
        "target": "es2022",
        "outDir": "dist",
        "declaration": true,          // Generate .d.ts
        "sourceMap": true,

        // Paths — tsconfig-relative; don't add baseUrl (TS 7 hard-errors on it, TS5102)
        "paths": { "@/*": ["./src/*"] },

        // Strictness extras
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noFallthroughCasesInSwitch": true,
        "forceConsistentCasingInFileNames": true
    },
    "include": ["src"],
    "exclude": ["node_modules", "dist"]
}

深入了解:加载 ./references/config-strict.md,了解严格模式迁移、monorepo 配置和项目引用。

常见问题

问题原因修复方法
any 泄漏any 会禁用其涉及的所有内容的类型检查改用 unknown 并进行收窄
as 断言隐藏错误断言不会在运行时进行检查使用类型守卫或验证(Zod)
enum 的问题数字枚举不具备类型安全性,反向映射容易造成混淆使用 as const 对象或字符串字面量联合类型
object 与 Record、{} 的区别{} 匹配任何非 null 值,object 表示非原始类型要表示“任意对象”,请使用 Record<string, unknown>
数组索引访问默认情况下,arr[999] 返回 T 而不是 T | undefined启用 noUncheckedIndexedAccess
可选与 undefined{ x?: string } 允许缺少键,{ x: string | undefined } 要求键存在明确选择所需语义
! 非空断言会关闭 null 检查,但不影响运行时行为使用 ?? defaultValue 或适当的 null 检查
结构类型意外之处{ a: 1, b: 2 } 可赋值给 { a: number }使用品牌类型实现名义类型

品牌类型 / 名义类型

// Prevent accidentally mixing types that are structurally identical
type UserId = string & { readonly __brand: "UserId" };
type OrderId = string & { readonly __brand: "OrderId" };

function createUserId(id: string): UserId { return id as UserId; }

function getUser(id: UserId) { /* ... */ }

const userId = createUserId("u-123");
const orderId = "o-456" as OrderId;

getUser(userId);   // OK
getUser(orderId);  // Error: OrderId not assignable to UserId

运行时验证(Zod 4)

import { z } from "zod";

// Define schema (Zod 4: string formats are top-level - z.email(), not z.string().email())
const UserSchema = z.object({
    id: z.number(),
    name: z.string().min(1),
    email: z.email(),
    role: z.enum(["admin", "user"]),
    settings: z.object({
        theme: z.enum(["light", "dark"]).default("light"),
    }).optional(),
});

// Infer type from schema
type User = z.infer<typeof UserSchema>;

// Validate
const user = UserSchema.parse(untrustedData);       // throws on invalid
const result = UserSchema.safeParse(untrustedData);  // returns { success, data/error }

需要了解的 Zod 4 变化(如果你熟悉 Zod 3):字符串格式已移至顶层 (z.email()、z.uuid()、z.url()——z.string().email() 这种方法形式已弃用); 错误定制统一使用单个 error 参数(不再支持 invalid_type_error / required_error);解析速度更快,并提供可进行 tree-shaking 的 zod/mini 入口点。

参考文件

深入了解特定主题时,可加载以下文件。每个文件均可独立阅读。

参考文件加载时机
./references/type-system.md高级类型、品牌类型、类型级编程、satisfies 运算符
./references/generics-patterns.md泛型约束、条件类型、映射类型、模板字面量、递归类型
./references/utility-types.md所有内置实用工具类型及示例、自定义实用工具类型
./references/config-strict.mdtsconfig 深入介绍、严格模式迁移、项目引用、monorepo 设置
./references/ts7-native-compiler.md采用 TS 7 原生(Go)编译器:无 JS API、bin 歧义、生态系统无法采用情况、基准测试与是否继续的决策
./references/ecosystem.mdZod/Valibot、类型安全的 API 客户端、ORM 类型、使用 Vitest 进行测试

另请参阅

  • testing-ops - 跨语言测试策略
  • ci-cd-ops - TypeScript CI 流水线、CI 中的类型检查

评论

支持 Markdown