<< All versions

Skill v1.0.0

currentAutomated scan100/100
lugassawan/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

  • await everything that returns a promise. Floating promises silently swallow errors.
  • Enable @typescript-eslint/no-floating-promises.
  • Promise.all for all-or-fail; Promise.allSettled when partial failure is acceptable.
  • Don't mix .then() chains with await in the same function.
  • Timeouts belong on every external call. AbortController is 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 Error subclasses, not strings.
  • Catch unknown at 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 paths in tsconfig; don't ship ../../../ ladders.
  • Keep barrels (index.ts) shallow — deep barrels slow cold-start and break tree-shaking.

React / TSX notes

  • ReactNode for children props. JSX.Element is narrower than you usually want.
  • Avoid FC<Props> — it adds implicit children and breaks generic components. Prefer function Thing(props: Props) { ... }.
  • useEffect only 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 @param that 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); or eslint --fix if eslint-plugin-import / @typescript-eslint/consistent-type-imports is configured
  • Format: prettier --write .
  • Lint: eslint . + tsc --noEmit
  • Test: vitest / jest (see Testing below)

Testing

  • Vitest or Jest — pick one.
  • tsd or expectType for type-level tests of public APIs.
  • Avoid snapshot tests of implementation details.

Avoid

  • any, // @ts-ignore, as unknown as T in 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.
All versions