Advanced TypeScript
Advanced TypeScript patterns for agents — generic types, conditional types, mapped types, discriminated unions, type guards, utility types, declaration files, strict mode, and module resolution.
You are an autonomous agent that writes and maintains TypeScript code. Your role is to leverage the type system to catch bugs at compile time, produce self-documenting code, and build APIs that guide consumers toward correct usage through types alone.
## Key Points
- Use generics when a function or type works with multiple types while preserving relationships: `function first<T>(arr: T[]): T | undefined`.
- Constrain generics with `extends` to narrow the accepted types: `function getLength<T extends { length: number }>(item: T): number`.
- Use default type parameters for common cases: `type Response<T = unknown> = { data: T; status: number }`.
- Name generic parameters meaningfully for complex generics: `TInput`, `TOutput`, `TKey` instead of single letters when clarity demands it.
- Use conditional types for type-level branching: `type IsString<T> = T extends string ? true : false`.
- Use `infer` to extract types within conditional expressions: `type ReturnOf<T> = T extends (...args: any[]) => infer R ? R : never`.
- Conditional types distribute over unions: `IsString<string | number>` becomes `true | false`.
- Use conditional types in library and utility code. Avoid them in application-level types where simpler constructs work.
- Transform existing types with mapped types: `type Readonly<T> = { readonly [K in keyof T]: T[K] }`.
- Use key remapping with `as`: `type Getters<T> = { [K in keyof T as `get${Capitalize<K & string>}`]: () => T[K] }`.
- Combine with conditional types for selective transformation: make only string properties optional, for example.
- Understand built-in mapped types before building custom ones.
## Quick Example
```
type Result<T> = { status: 'success'; data: T } | { status: 'error'; error: Error }
```skilldb get autonomous-agent-skills/typescript-advancedFull skill: 99 linesAdvanced TypeScript
You are an autonomous agent that writes and maintains TypeScript code. Your role is to leverage the type system to catch bugs at compile time, produce self-documenting code, and build APIs that guide consumers toward correct usage through types alone.
Philosophy
TypeScript's type system is a tool for expressing intent. The goal is not to make the compiler happy — it is to encode domain rules, prevent invalid states, and make incorrect code impossible to write. Invest in precise types upfront; they pay dividends in fewer runtime errors and better developer experience.
Techniques
Generic Types
- Use generics when a function or type works with multiple types while preserving relationships:
function first<T>(arr: T[]): T | undefined. - Constrain generics with
extendsto narrow the accepted types:function getLength<T extends { length: number }>(item: T): number. - Use default type parameters for common cases:
type Response<T = unknown> = { data: T; status: number }. - Name generic parameters meaningfully for complex generics:
TInput,TOutput,TKeyinstead of single letters when clarity demands it.
Conditional Types
- Use conditional types for type-level branching:
type IsString<T> = T extends string ? true : false. - Use
inferto extract types within conditional expressions:type ReturnOf<T> = T extends (...args: any[]) => infer R ? R : never. - Conditional types distribute over unions:
IsString<string | number>becomestrue | false. - Use conditional types in library and utility code. Avoid them in application-level types where simpler constructs work.
Mapped Types
- Transform existing types with mapped types:
type Readonly<T> = { readonly [K in keyof T]: T[K] }. - Use key remapping with
as:type Getters<T> = { [K in keyof T asget${Capitalize<K & string>}]: () => T[K] }. - Combine with conditional types for selective transformation: make only string properties optional, for example.
- Understand built-in mapped types before building custom ones.
Template Literal Types
- Use template literal types for string pattern enforcement:
type EventName =on${Capitalize<string>}``. - Combine with mapped types for type-safe event systems or API route definitions.
- Use for CSS unit types:
type CSSLength =${number}${'px' | 'rem' | 'em'}``. - Keep template literal types focused. Overly complex string type patterns become unreadable.
Discriminated Unions
- Model states with discriminated unions using a shared literal type field:
type Result<T> = { status: 'success'; data: T } | { status: 'error'; error: Error } - Use
switchorifon the discriminant field for exhaustive handling. - Add a
neverdefault case to catch unhandled variants at compile time. - Prefer discriminated unions over boolean flags.
{ loading: boolean; error: boolean; data: T | null }has impossible states; a union does not.
Type Guards
- Write custom type guards with
isreturn type:function isUser(val: unknown): val is User. - Use
typeoffor primitive narrowing andinoperator for property checks. - Use
satisfiesoperator to validate a value matches a type without widening:const config = { ... } satisfies Config. - Validate external data (API responses, user input) at runtime boundaries with type guards or validation libraries like Zod.
Utility Types
Pick<T, K>: Select specific properties from a type.Omit<T, K>: Remove specific properties from a type.Partial<T>: Make all properties optional. Useful for update operations.Required<T>: Make all properties required. Useful for ensuring complete configuration.Record<K, V>: Create an object type with specified keys and value types.Extract<T, U>andExclude<T, U>: Filter union types.NonNullable<T>: Removenullandundefinedfrom a type.- Compose utility types:
Partial<Pick<User, 'name' | 'email'>>for targeted partial updates.
Declaration Files
- Write
.d.tsfiles to type untyped JavaScript libraries or global declarations. - Use
declare modulefor augmenting existing module types. - Use
declare globalto extend global types (Window, NodeJS.ProcessEnv). - Check DefinitelyTyped (
@types/*) before writing custom declarations.
Strict Mode
- Enable all strict flags in
tsconfig.json:"strict": true. - Key strict options:
strictNullChecks(no implicit null),noImplicitAny(no untyped variables),strictFunctionTypes(correct function variance). - Enable
noUncheckedIndexedAccessto treat index access as potentially undefined. - Strict mode catches real bugs. Never disable it to "make things easier."
Module Resolution
- Use
"moduleResolution": "bundler"for modern bundler-based projects or"nodenext"for Node.js packages. - Configure path aliases in
tsconfig.jsonwithpathsand ensure the bundler resolves them too. - Use
import typefor type-only imports to ensure they are erased at compile time. - Understand the difference between
require(CommonJS) andimport(ESM). Configure"module"appropriately.
Best Practices
- Start with strict mode on every new project. Retrofitting strict mode onto a large codebase is painful.
- Use
unknowninstead ofanyfor values of uncertain type.unknownforces safe narrowing. - Use
as constfor literal type inference on objects and arrays. - Export types alongside their implementations. Consumers should not need to reconstruct your types.
- Use Zod, Valibot, or ArkType for runtime validation that generates TypeScript types.
Anti-Patterns
- Using
anyto silence type errors instead of fixing the underlying type issue. - Casting with
aswhen a type guard or proper narrowing would be safer. - Disabling strict mode or individual strict checks to avoid fixing type errors.
- Creating overly complex conditional types that no one on the team can read or maintain.
- Using
@ts-ignoreor@ts-expect-errorwithout a comment explaining why. - Defining all types as
interfacewhentypewould be more appropriate (unions, intersections, primitives). - Not using discriminated unions for state management, leading to impossible state combinations.
- Ignoring the
satisfiesoperator and usingasfor type validation instead.
Install this skill directly: skilldb add autonomous-agent-skills
Related Skills
Undo Redo Implementation
Implementing undo/redo functionality with command patterns, state history, and memory efficiency
URL Routing Patterns
Implementing URL routing in web applications with RESTful design and modern patterns
Web Research Synthesis
Effective web research techniques including query formulation, source evaluation, cross-referencing, and synthesizing findings into actionable intelligence.
Webhook Integration
Implementing and consuming webhooks with endpoint security, signature verification, idempotency handling, retry logic, payload validation, and dead letter queues.
WebSocket Implementation
Real-time communication with WebSockets including connection lifecycle, reconnection strategies, heartbeat patterns, room/channel design, scaling, authentication, and graceful disconnection handling.
YAML and TOML Processing
Working with YAML and TOML configuration formats including multiline strings, anchors, TOML tables, comment preservation, common YAML gotchas, and format selection guidance.