<< All versions
Prefer
Skill v1.0.0
currentAutomated scan100/100lugassawan/swe-workbench/language-typescript
──Details
PublishedSeptember 27, 2026 at 10:57 AM
Content Hashsha256:dc9f5393a8f3d2a9...
Git SHAe387170b21ee
──Files
Files (1 file, 4.1 KB)
SKILL.md4.1 KBactive
SKILL.md · 125 lines · 4.1 KB
version: "1.0.0" name: language-typescript description: TypeScript and JavaScript idioms — strict mode, async patterns, and Node. Auto-load when working with .ts, .tsx, .js, .jsx files, package.json, or when the user mentions TypeScript, JavaScript, type safety, or tsconfig.
<!-- preload-canary: SWB-PRELOAD-LANGUAGE-TYPESCRIPT -->
TypeScript / JavaScript
Strict mode or nothing
Enable in tsconfig.json:
json
{"compilerOptions": {"strict": true,"noUncheckedIndexedAccess": true,"noImplicitOverride": true,"exactOptionalPropertyTypes": true}}
Without these, types lie.
Prefer unknown over any
any turns off the type system. unknown forces narrowing.
ts
function parse(input: unknown): User {if (!isUser(input)) throw new Error("invalid user");return input;}
Discriminated unions over enums
Enums have runtime quirks and poor exhaustiveness. Use string-literal unions with a discriminant.
ts
type Event =| { kind: "click"; x: number; y: number }| { kind: "submit"; form: FormData };function handle(e: Event) {switch (e.kind) {case "click": return trackClick(e.x, e.y);case "submit": return submit(e.form);default: {const _exhaustive: never = e; return _exhaustive;}}}
Branded types for domain primitives
Stop UserId from being passed where an OrderId is expected.
ts
type Brand<K, T> = K & { readonly __brand: T };type UserId = Brand<string, "UserId">;type OrderId = Brand<string, "OrderId">;const makeUserId = (s: string): UserId => s as UserId;
Async patterns
awaiteverything that returns a promise. Floating promises silently swallow errors.- Enable
@typescript-eslint/no-floating-promises. Promise.allfor all-or-fail;Promise.allSettledwhen partial failure is acceptable.- Don't mix
.then()chains withawaitin the same function. - Timeouts belong on every external call.
AbortControlleris the standard.
ts
const ac = new AbortController();const t = setTimeout(() => ac.abort(), 5_000);try {const r = await fetch(url, { signal: ac.signal });return await r.json();} finally {clearTimeout(t);}
Structural typing gotchas
TypeScript types are shapes, not identities. Two unrelated types with the same fields are interchangeable. Brand when you need nominal behavior.
Error handling
- Throw
Errorsubclasses, not strings. - Catch
unknownat boundaries; narrow before use. - For domain code, consider
Result<T, E>-style unions over throwing — explicit, typed, exhaustively handled.
Modules and imports
- ESM (
"type": "module") in new projects. - Absolute imports via
pathsintsconfig; don't ship../../../ladders. - Keep barrels (
index.ts) shallow — deep barrels slow cold-start and break tree-shaking.
React / TSX notes
ReactNodefor children props.JSX.Elementis narrower than you usually want.- Avoid
FC<Props>— it adds implicitchildrenand breaks generic components. Preferfunction Thing(props: Props) { ... }. useEffectonly for synchronizing with external systems. Derived state belongs in render.
Doc comments
- TSDoc/JSDoc —
/** ... */: one-line summary. The type signature already documents shape, so skip@paramthat just restates a typed parameter name.
ts
/** Returns the user's active orders, most recent first. */function activeOrders(userId: string): Order[] { ... }
Tooling
- Imports:
npx organize-imports-cli(reliable regardless of ESLint config); oreslint --fixifeslint-plugin-import/@typescript-eslint/consistent-type-importsis configured - Format:
prettier --write . - Lint:
eslint .+tsc --noEmit - Test:
vitest/jest(see Testing below)
Testing
- Vitest or Jest — pick one.
tsdorexpectTypefor type-level tests of public APIs.- Avoid snapshot tests of implementation details.
Avoid
any,// @ts-ignore,as unknown as Tin production code.- Non-null assertions (
!) without a comment explaining why. Object,Function,{}as types — they are never what you want.- Classes where a function and a closure would do.