From dh
Reviews TypeScript code for strict mode, ESM, type safety, branded types, discriminated unions, and anti-patterns. Activates automatically on tsconfig.json, .ts, or .tsx files.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dh:code-review-typescriptThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Stack-specific rules loaded by `dh:code-reviewer` when `tsconfig.json`, `*.ts`, or `*.tsx` files are detected.
Stack-specific rules loaded by dh:code-reviewer when tsconfig.json, *.ts, or *.tsx files are detected.
tsconfig.json must enable strict: true — this covers noImplicitAny, strictNullChecks, strictFunctionTypes, and othersexactOptionalPropertyTypes: true is required in new projects — prevents undefined from being assigned to optional propertiesnoUncheckedIndexedAccess: true is required when indexing arrays or records — prevents silent undefined propagation@ts-ignore comment without an accompanying explanation comment is a blocking finding@ts-expect-error is preferred over @ts-ignore — it fails if the error goes awayany type without an explanatory comment is a blocking findingas SomeType) without runtime validation at the same boundary are a blocking findingunknown is the correct type for values from external sources — validate before narrowing, not afterobject as a type is not meaningful — use Record<string, unknown> or a specific interfacevalue!) without a comment explaining why null is impossible are a blocking findingisLoading, isError, isSuccess as separate booleans allows impossible combinations// WRONG: boolean flags allow impossible states
interface State {
isLoading: boolean;
isError: boolean;
data: User | null;
}
// RIGHT: discriminated union — impossible states are unrepresentable
type State =
| { status: "loading" }
| { status: "error"; error: Error }
| { status: "success"; data: User };
UserId and OrderId are both string at runtime — without brands, they are interchangeable to the type checkertype UserId = string & { readonly _brand: "UserId" };
type OrderId = string & { readonly _brand: "OrderId" };
function makeUserId(id: string): UserId {
return id as UserId;
}
require() calls are a blocking finding — use import syntaximport type must be used for type-only imports — prevents runtime errors and improves tree-shakingimport() must be typed with the expected module shapeawait or .then()/.catch()) are a blocking findingPromise.all is required for parallel independent async operations — sequential await in a loop is an anti-pattern when operations are independentawait inside a for loop that processes independent items is a blocking findingas UserType casts on external dataJSON.parse(text) as MyType is a blocking findingprocess.env.API_KEY! without validation is a blocking findingsatisfies Operatorsatisfies is preferred over explicit type annotations for config objects and record literals — preserves the literal type while validating against the declared type// RIGHT: satisfies preserves literal types
const config = {
port: 3000,
host: "localhost",
} satisfies ServerConfig;
// config.port is typed as 3000, not number
// WRONG: any without comment
function process(data: any) { ... }
// RIGHT: specific type or documented any
function process(data: unknown) {
if (!isUserEvent(data)) throw new TypeError("Expected UserEvent");
...
}
// WRONG: floating promise
sendMetrics(event);
// RIGHT: awaited or explicitly fire-and-forget
void sendMetrics(event); // intentionally not awaited — best-effort telemetry
// or
await sendMetrics(event);
npx claudepluginhub jamie-bitflight/claude_skills --plugin dhEnforces TypeScript type safety with strict mode, no `any`, and discriminated unions. Use when writing or reviewing TypeScript code.
Guides TypeScript code with pedantic best practices: strict tsconfig flags like noUncheckedIndexedAccess, discriminated unions over assertions, Zod runtime validation, barrel exports, as const, ESLint rules.
TypeScript type system, strict mode, and TS-specific patterns beyond JavaScript fundamentals. Invoke whenever task involves any interaction with TypeScript code — writing, reviewing, refactoring, debugging .ts/.tsx files, type definitions, generics, narrowing, tsconfig, or type-level programming.