Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
xobotyi avatar

Typescript

  • 4 installs
  • 19 repo stars
  • Updated August 1, 2026
  • xobotyi/cc-foundry

Helps with ai & agent building tasks.

About

typescript is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.

  • typescript
  • AI & Agent Building
  • AI-coding skill

Typescript by the numbers

  • 4 all-time installs (skills.sh)
  • Ranked #13,348 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/xobotyi/cc-foundry --skill typescript

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs4
repo stars19
Last updatedAugust 1, 2026
Repositoryxobotyi/cc-foundry

What it does

Helps with ai & agent building tasks.

Files

SKILL.mdMarkdownGitHub ↗

TypeScript

<prerequisite> This skill extends the JavaScript skill. You must load javascript first — naming, ternary operator rules, async patterns, and module conventions are defined there and not duplicated here. </prerequisite>

Types encode intent. Let the compiler prove the rest.

TypeScript's value is in catching bugs at compile time. Write types that express your domain; let inference handle the obvious. Never fight the type system — if you need as or any, the types are wrong.

References

TopicReferenceContents
Generics, utility types, type-level programming[${CLAUDE_SKILL_DIR}/references/generics.md]Utility type tables, conditional/mapped type examples, infer, template literals
Narrowing, type guards, discriminated unions[${CLAUDE_SKILL_DIR}/references/narrowing.md]typeof/instanceof/in examples, exhaustive switch, type predicates, assertion fns
tsconfig options, module resolution, project setup[${CLAUDE_SKILL_DIR}/references/configuration.md]Base/strict/module configs, library setup, compiler directives, project structure
Branded types, overloads, class patterns, enums[${CLAUDE_SKILL_DIR}/references/patterns.md]Interface vs type examples, assertion patterns, enum anti-patterns, callback types

Type Safety

  • `strict: true` always. No exceptions. It enables strictNullChecks,

noImplicitAny, strictFunctionTypes, and other critical checks.

  • `unknown` over `any`. Use unknown and narrow with type guards. any disables

type checking entirely. Reserve any for migration or test mocks only — document why.

  • No non-null assertions (`!`) without justification. Prefer narrowing. If ! is

truly needed, add a comment explaining why the value cannot be null.

  • No type assertions (`as`) for object literals. Use type annotations (: Foo)

instead — assertions hide missing/extra property errors.

unknown vs any Decision

SituationUse
Value from external source (API, JSON.parse, user input)unknown
Function accepts anything, passes through without touchingunknown
Migrating JS to TS incrementallyany (temporary, with comment)
Test mock that intentionally bypasses type checkingany (with comment)

The {} Type

{} means "any non-nullish value" — almost never what you want.

TypeAllows
unknownEverything (null, undefined, primitives, objects)
objectNon-primitive, non-null values
{}Any non-nullish value (primitives included)
Record<string, unknown>Objects with string keys

Prefer unknown for opaque values, Record<string, unknown> for dict-like objects, object when you need "any non-primitive".

Type Annotations

  • Omit trivially inferred types. Don't annotate const x: number = 5 or

const s: string = "hello". The compiler infers these correctly.

  • Annotate complex return types. When inference produces opaque or wide types,

annotate explicitly for readability.

  • Annotate function signatures at API boundaries. Exported functions and public

methods should have explicit parameter and return types.

  • Use `import type` for type-only imports. Enforced by verbatimModuleSyntax.

Use export type for type re-exports — required for isolatedModules.

  • Annotate for precision with structural types. Annotate at declaration so errors

appear where the bug is, not at distant call sites.

Interfaces and Types

  • `interface` for object shapes. Better error messages, IDE support, and performance.
  • `type` for everything else — unions, intersections, tuples, function types,

mapped/conditional types.

  • Decision rule: Object shape with known properties? interface. Everything else?

type. Pick one pattern per kind and stay consistent within a project.

  • No empty interfaces. Use a branded type or discriminated union as a marker.
  • No `namespace`. Use ES modules. namespace is legacy.
  • No wrapper types. string not String, number not Number.
  • Use interfaces for data shapes, not classes. A class used purely as a data shape

adds unnecessary overhead.

Null Handling

  • Prefer optional `?` over `| undefined` for fields and parameters. | undefined

forces callers to pass undefined explicitly.

  • Don't include `null`/`undefined` in type aliases. Keep nullability at the use site:

function getUser(): User | null not type MaybeUser = User | null.

  • Null narrowing: != null checks both null and undefined (the one valid == use).

?. for optional access. ?? for defaults.

Generics

  • Name type parameters descriptively when meaning is non-obvious. T is fine for

single-parameter generics; use TKey, TValue, TItem for multiple parameters.

  • Constrain generics with extends when possible. <T extends string> is better

than <T> if T must be a string.

  • Keep generic constraints tight<T extends Record<string, unknown>> is better

than <T extends object> when you need string keys.

  • Don't add unused type parameters. Every generic must appear in the signature.
  • Avoid return-type-only generics. If a generic appears only in the return type, it

cannot be inferred and forces callers to guess.

  • Let inference work. Don't specify type arguments when the compiler can infer them:

identity("hello") not identity<string>("hello").

  • Use type parameters in constraints: <T, K extends keyof T> to relate parameters.
  • Generic parameter defaults: interface Container<T, U = T[]> — omitted type args

fall back to the default.

  • `NoInfer<T>` (TS 5.4+) prevents a parameter from being an inference site — use when

a parameter should be constrained by other params, not drive inference.

Utility Types

Prefer built-in utility types over hand-rolling equivalents. Key types: Partial, Pick, Omit, Record, Exclude, Extract, ReturnType, Parameters, Awaited, NoInfer. Use explicit interfaces when the type represents a distinct domain concept. See ${CLAUDE_SKILL_DIR}/references/generics.md for the full catalog and usage guidance.

Conditional types (T extends U ? X : Y), mapped types ({ [P in keyof T]: ... }), and template literal types (` ${T}Changed ) are advanced tools — use for library code and framework types. See ${CLAUDE_SKILL_DIR}/references/generics.md for distributive behavior, infer`, modifier removal, and key remapping.

Complexity Budget

TierToolsUse When
Simpleinterface, type alias, unionAlways — default choice
ModeratePartial, Pick, Omit, RecordWell-known transformations
AdvancedConditional, mapped, template literalLibrary code, framework types
ExpertRecursive types, complex infer chainsRarely — last resort

Stay at the lowest tier that solves your problem. If you can't explain what a type does in one sentence, it's too complex — split it, simplify it, or use explicit interfaces.

Narrowing

  • Prefer discriminated unions for variant types. Add a kind or type literal

field to each variant.

  • Use exhaustive switches. Add `default: { const _exhaustive: never = value;

return _exhaustive; }` to catch unhandled variants at compile time.

  • Type predicates for reusable guards: function isFish(pet: Animal): pet is Fish.

Use when filtering arrays or in multiple call sites.

  • Assertion functions: `function assertIsError(value: unknown): asserts value is

Error` — use for validation at boundaries.

  • `typeof`, `instanceof`, `in` — use JavaScript narrowing constructs; TypeScript

understands them natively.

  • `typeof null === "object"` pitfall. Always check for null separately before

typeof object checks.

  • `in` operator and optional properties: if Human has swim?, "swim" in animal

narrows to Fish | Human, not just Fish.

  • Truthiness narrowing pitfall: fails on "", 0, NaN, false. Prefer explicit

null checks over truthiness when these values are valid.

  • Equality narrowing: x === y narrows both to their common type. != null checks

both null and undefined.

Enums

  • Prefer union types over enums when values are simple string literals:

type Status = "active" | "inactive" is simpler than enum Status.

  • Prefer string enums over numeric enums when an enum is needed. String enums have

meaningful runtime values and readable debug output.

  • Never use numeric enums with implicit values — always assign explicit values.
  • Never coerce enums to booleans. Compare explicitly: level !== Level.NONE, not

!!level. Numeric enum value 0 is falsy.

  • Never mix numeric and string members in the same enum.
  • Use enums over unions when you need a runtime object (iteration, lookup), a

namespace for related constants, or reverse mapping.

Type Assertions

  • Prefer annotations over assertions. : Foo catches errors; as Foo hides them.
  • Always use `as` syntax, never angle brackets (<Foo>value) — angle brackets

conflict with JSX.

  • Assertions are justified when you genuinely know more than the compiler: values

from JSON.parse, DOM API returning wider types, trusted external sources.

  • Double assertions through `unknown`: value as unknown as Foo. Never use any

as the intermediate type.

Overloads

  • Prefer union types over overloads when parameter types differ but logic is shared.
  • Prefer optional parameters over overloads when signatures differ only in trailing

params.

  • When overloads are necessary, put specific signatures before general ones —

TypeScript picks the first matching overload.

Class Patterns

  • Omit `public` — it's the default. Only use public on non-readonly constructor

parameter properties.

  • Use `private` for internal state, protected for subclass access.
  • Use `readonly` on properties never reassigned after construction.
  • Use constructor parameter properties to avoid boilerplate:

constructor(private readonly db: Database) {}.

  • Initialize fields where declared when possible: private count = 0.
  • Require `override` keyword on overridden methods (noImplicitOverride).

Callback Types

  • Use `void` return for callbacks whose return value is ignored.
  • Don't use optional parameters in callbacks — callers can always ignore extra args.

(data: unknown, elapsed: number) => void not (data: unknown, elapsed?: number) => any.

Branded Types

Use branded types for nominal-like safety when structural typing is too permissive: domain IDs (UserId vs OrderId), validated strings (Email), units (Meters vs Kilometers). Pattern: type UserId = string & { readonly __brand: unique symbol }. Keep the branding mechanism consistent across the project — unique symbol is most robust.

Array Type Syntax

Use T[] for simple element types (string[], User[]). Use Array<T> for complex element types (Array<string | number>). Same rule applies to readonly variants.

Configuration (tsconfig.json)

  • `strict: true` always. Non-negotiable. Also enable noUncheckedIndexedAccess

and noImplicitOverride.

  • Module resolution: module: "NodeNext" when transpiling with tsc;

module: "preserve" with external bundlers (Vite, esbuild, Bun). Use verbatimModuleSyntax: true in both cases.

  • Target: es2022 (stable). Set lib to include dom for browser projects.
  • Never `@ts-ignore`. Use @ts-expect-error in tests only, with a comment.

Never @ts-nocheck in production.

  • Keep `tsconfig.json` minimal. Use extends for shared configs. Separate

tsconfig.build.json for builds (excludes tests, scripts).

See ${CLAUDE_SKILL_DIR}/references/configuration.md for the full options catalog, library project setup, and project structure guidance.

Application

When writing TypeScript code:

  • Apply all conventions silently — don't narrate each rule being followed.
  • Match the project's existing patterns (interface vs type preference, enum style).
  • If an existing codebase contradicts a convention, follow the codebase and flag the

divergence once.

When reviewing TypeScript code:

  • Cite the specific issue and show the fix inline.
  • Don't lecture — state what's wrong and how to fix it.

Integration

The javascript skill is a hard prerequisite. The JavaScript skill governs code patterns; this skill governs type-level choices.

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.