Awesome-claude-code-toolkit typescript-advanced
Advanced TypeScript patterns including generics, conditional types, mapped types, template literals, and type guards
install
source · Clone the upstream repo
git clone https://github.com/rohitg00/awesome-claude-code-toolkit
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/rohitg00/awesome-claude-code-toolkit "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/typescript-advanced" ~/.claude/skills/rohitg00-awesome-claude-code-toolkit-typescript-advanced && rm -rf "$T"
manifest:
skills/typescript-advanced/SKILL.mdsource content
TypeScript Advanced
Generics with Constraints
interface HasId { id: string; } function findById<T extends HasId>(items: T[], id: string): T | undefined { return items.find(item => item.id === id); } function groupBy<T, K extends string | number>( items: T[], keyFn: (item: T) => K ): Record<K, T[]> { return items.reduce((acc, item) => { const key = keyFn(item); (acc[key] ??= []).push(item); return acc; }, {} as Record<K, T[]>); } type ApiResponse<T> = { data: T; meta: { page: number; total: number }; }; async function fetchApi<T>(url: string): Promise<ApiResponse<T>> { const res = await fetch(url); return res.json(); }
Conditional Types
type IsString<T> = T extends string ? true : false; type Flatten<T> = T extends Array<infer U> ? U : T; type UnwrapPromise<T> = T extends Promise<infer U> ? UnwrapPromise<U> : T; type FunctionReturn<T> = T extends (...args: any[]) => infer R ? R : never; type ExtractRouteParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}` ? Param | ExtractRouteParams<Rest> : T extends `${string}:${infer Param}` ? Param : never; type Params = ExtractRouteParams<"/users/:userId/posts/:postId">;
Mapped Types
type Readonly<T> = { readonly [K in keyof T]: T[K] }; type Optional<T> = { [K in keyof T]?: T[K] }; type Nullable<T> = { [K in keyof T]: T[K] | null }; type PickByType<T, V> = { [K in keyof T as T[K] extends V ? K : never]: T[K]; }; interface User { id: string; name: string; age: number; active: boolean; } type StringFields = PickByType<User, string>; type EventMap<T> = { [K in keyof T as `on${Capitalize<string & K>}`]: (value: T[K]) => void; }; type UserEvents = EventMap<{ login: User; logout: string }>;
Discriminated Unions
type Result<T, E = Error> = | { ok: true; value: T } | { ok: false; error: E }; function divide(a: number, b: number): Result<number, string> { if (b === 0) return { ok: false, error: "Division by zero" }; return { ok: true, value: a / b }; } const result = divide(10, 2); if (result.ok) { console.log(result.value); } else { console.error(result.error); } type Shape = | { kind: "circle"; radius: number } | { kind: "rect"; width: number; height: number } | { kind: "triangle"; base: number; height: number }; function area(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "rect": return shape.width * shape.height; case "triangle": return 0.5 * shape.base * shape.height; } }
Type Guards
function isNonNull<T>(value: T | null | undefined): value is T { return value != null; } function hasProperty<K extends string>( obj: unknown, key: K ): obj is Record<K, unknown> { return typeof obj === "object" && obj !== null && key in obj; } const values = [1, null, 2, undefined, 3].filter(isNonNull); function assertNever(value: never): never { throw new Error(`Unexpected value: ${value}`); }
Utility Type Combinations
type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]; }; type StrictOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> & { [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>> }[Keys]; type UpdateUserInput = RequireAtLeastOne<{ name: string; email: string; age: number }>;
Anti-Patterns
- Using
instead ofany
for values of uncertain typeunknown - Type assertions (
) when a type guard would be saferas - Overly complex generic signatures that reduce readability
- Not using discriminated unions for state machines or result types
- Using
when a union of string literals sufficesenum - Ignoring
in tsconfigstrictNullChecks
Checklist
-
enabled in tsconfigstrict: true -
used instead ofunknown
for external dataany - Type guards validate runtime types safely
- Discriminated unions model state with exhaustive switches
- Generic constraints (
) prevent misuseextends - Mapped types used to derive related types from a source
- Utility types (
,Pick
,Omit
) preferred over manual retypingPartial - Template literal types used for string pattern enforcement