一键导入
typescript-expert
Use this skill when writing, reviewing, or refactoring TypeScript code for type safety, idiomatic patterns, and modern best practices.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use this skill when writing, reviewing, or refactoring TypeScript code for type safety, idiomatic patterns, and modern best practices.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use this skill when you need to diagnose and fix React 19 performance issues (render churn, slow updates, Suspense/Transitions, memoization, profiling, and React Compiler).
Write clean, behavior-focused unit/integration tests that remain trustworthy when code is written or modified by agents (prevents “test weakening”, enforces invariants, and adds CI guardrails).
Use this skill when you are creating or updating Agent Skills in your project (structure, YAML frontmatter, naming, and progressive disclosure).
Use this skill when designing or refactoring boundaries, responsibilities, and change drivers using practical software architecture “hard parts” thinking + SRP.
Use this skill when you need a Bun runbook (dev, build, lint, typecheck, tests, migrations, and verification steps).
Use this skill when you need a thorough code hygiene pass (dead code, lint escapes, consistency, formatting drift, and subtle smells) on touched files.
| name | typescript-expert |
| description | Use this skill when writing, reviewing, or refactoring TypeScript code for type safety, idiomatic patterns, and modern best practices. |
| metadata | {"applyTo":"**/*.ts, **/*.tsx"} |
Universal TypeScript best practices for type safety, maintainability, and performance.
Types are documentation the compiler enforces.
Write types that make illegal states unrepresentable. Prefer compile-time errors over runtime errors.
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"exactOptionalPropertyTypes": true
}
}
unknown Over any// ❌ any bypasses all type checking
function process(data: any) {
return data.foo.bar; // No error, crashes at runtime
}
// ✅ unknown forces narrowing
function process(data: unknown) {
if (typeof data === "object" && data !== null && "foo" in data) {
// Safe to access
}
}
as const for Literal Types// Type: { method: string }
const req = { method: "GET" };
// Type: { readonly method: "GET" }
const req = { method: "GET" } as const;
// Arrays become readonly tuples
const colors = ["red", "green", "blue"] as const;
// Type: readonly ["red", "green", "blue"]
// typeof guard
function format(value: string | number) {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toFixed(2);
}
// in operator
function move(animal: Fish | Bird) {
if ("swim" in animal) return animal.swim();
return animal.fly();
}
// Custom type predicate
function isString(value: unknown): value is string {
return typeof value === "string";
}
Model state and variants with a shared discriminant property:
type Result<T, E = Error> =
| { status: "ok"; data: T }
| { status: "error"; error: E };
function handle(result: Result<User>) {
if (result.status === "ok") {
console.log(result.data); // TS knows data exists
} else {
console.log(result.error); // TS knows error exists
}
}
nevertype Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side ** 2;
default:
const _exhaustive: never = shape;
throw new Error(`Unhandled: ${_exhaustive}`);
}
}
// ❌ Too loose
function getProp<T>(obj: T, key: string) {
return obj[key]; // Error
}
// ✅ Constrained
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
type Response<T = unknown, E = Error> = {
data: T | null;
error: E | null;
};
// ❌ Overloads are verbose
function parse(input: string): string;
function parse(input: number): number;
function parse(input: string | number) { return input; }
// ✅ Generic is cleaner
function parse<T extends string | number>(input: T): T {
return input;
}
// ❌ Unused generic
function greet<T>(name: string): string { return `Hello, ${name}`; }
// ✅ No generic needed
function greet(name: string): string { return `Hello, ${name}`; }
Partial<T> // All properties optional
Required<T> // All properties required
Pick<T, K> // Select properties
Omit<T, K> // Exclude properties
Record<K, V> // Key-value map
NonNullable<T> // Remove null/undefined
ReturnType<F> // Function return type
Parameters<F> // Function parameters as tuple
Awaited<T> // Unwrap Promise
Exclude<T, U> // Remove union members
Extract<T, U> // Keep union members
// Make all optional
type Draft<T> = Partial<T>;
// Select fields
type UserPreview = Pick<User, "id" | "name">;
// Exclude fields
type PublicUser = Omit<User, "password" | "email">;
// Typed dictionary
type UserMap = Record<string, User>;
// Remove nullability
type Defined<T> = NonNullable<T>;
type EventName = `on${Capitalize<"click" | "focus">}`;
// "onClick" | "onFocus"
type Route = `/${string}`;
type CSSValue = `${number}${"px" | "rem" | "%"}`;
infer// Extract return type
type Return<T> = T extends (...args: never[]) => infer R ? R : never;
// Unwrap Promise
type Unwrap<T> = T extends Promise<infer U> ? U : T;
// Array element type
type Element<T> = T extends (infer E)[] ? E : never;
// Add readonly
type Immutable<T> = { readonly [K in keyof T]: T[K] };
// Remove readonly
type Mutable<T> = { -readonly [K in keyof T]: T[K] };
// Rename keys
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
// ✅ Explicit type imports
import type { User, Config } from "./types";
import { createUser } from "./users";
// ✅ Inline type import
import { createUser, type User } from "./users";
verbatimModuleSyntax{
"compilerOptions": {
"verbatimModuleSyntax": true
}
}
Use interface for | Use type for |
|---|---|
| Object shapes | Unions |
| Extensible contracts | Intersections |
| Class implementations | Mapped types |
| Declaration merging | Function types |
// Interface for extensible shapes
interface User {
id: string;
name: string;
}
// Type for unions and compositions
type Status = "active" | "inactive";
type UserWithStatus = User & { status: Status };
void, Not any// ❌ any allows accidental use of return value
function run(cb: () => any) { cb(); }
// ✅ void prevents using return value
function run(cb: () => void) { cb(); }
// ❌ General overload first hides specific ones
declare function fn(x: unknown): unknown;
declare function fn(x: HTMLElement): number;
// ✅ Specific overloads first
declare function fn(x: HTMLDivElement): string;
declare function fn(x: HTMLElement): number;
declare function fn(x: unknown): unknown;
// ❌ Verbose
interface Moment {
utcOffset(b: number): Moment;
utcOffset(b: string): Moment;
}
// ✅ Union type
interface Moment {
utcOffset(b: number | string): Moment;
}
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
function divide(a: number, b: number): Result<number, string> {
if (b === 0) return { ok: false, error: "Division by zero" };
return { ok: true, value: a / b };
}
const result = divide(10, 2);
if (result.ok) {
console.log(result.value);
} else {
console.error(result.error);
}
class ValidationError extends Error {
constructor(
message: string,
public readonly field: string,
public readonly code: string
) {
super(message);
this.name = "ValidationError";
}
}
// ❌ Slower for type checker
type Extended = Base & { extra: string };
// ✅ Faster
interface Extended extends Base {
extra: string;
}
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./.tsbuildinfo"
}
}
{
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/ui" }
]
}
| You're doing... | Don't use | Use instead |
|---|---|---|
| Unknown input | any | unknown + narrowing |
| Operation result | T | null | Discriminated union |
| Immutable value | let | as const |
| Object shape | type | interface (if extendable) |
| Union/mapped | interface | type |
| Callback return | any | void |
| Type assertion | as Type | Type guard or narrowing |
| Deep nesting | Manual recursion | Utility types |
| Pattern | Problem | Fix |
|---|---|---|
any | Disables type checking | Use unknown |
as Type | Hides type errors | Narrow properly |
! non-null | Runtime error risk | Handle null case |
// @ts-ignore | Suppresses real errors | Fix the type |
| Unused generic | Adds complexity | Remove it |
Object type | Wrong type | Use object |