From harness-claude
Guides writing reusable, type-safe functions, classes, and interfaces using TypeScript generics. Use for multi-type operations, utility functions preserving types, constraints like extends, and inference.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Write reusable, type-safe functions and interfaces using TypeScript generics
Provides examples of advanced TypeScript patterns: generics with constraints, conditional types, mapped types, discriminated unions, and type guards. Useful for complex typing scenarios.
Masters TypeScript advanced types including generics, conditional types, mapped types, template literals, and utility types for type-safe applications. Use for complex type logic, reusable utilities, and compile-time safety in TS projects.
Guides TypeScript advanced types like generics, conditional types, mapped types, template literals, and utilities for type-safe libraries, APIs, and components. Use for complex type logic and inference.
Share bugs, ideas, or general feedback.
Write reusable, type-safe functions and interfaces using TypeScript generics
function wrap<T>(value: T): T[].extends when the body requires a specific shape: function getKey<T extends { id: string }>(item: T): string.function map<T, U>(arr: T[], fn: (item: T) => U): U[].interface Response<T = unknown> { data: T; status: number }.infer inside conditional types to extract sub-types: type Awaited<T> = T extends Promise<infer U> ? U : T.T for a single generic, TKey/TValue for maps, TResult for return types.// Generic identity — preserves exact type at call site
function identity<T>(value: T): T {
return value;
}
const n = identity(42); // type: 42 (literal)
const s = identity('hi'); // type: "hi" (literal)
// Constrained generic — body can access .length
function longest<T extends { length: number }>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
// Inferring the resolved type of a Promise
type Awaited<T> = T extends Promise<infer U> ? U : T;
type X = Awaited<Promise<string>>; // string
// Generic interface with default
interface ApiResponse<T = unknown> {
data: T;
error: string | null;
timestamp: number;
}
// Relating two type parameters
function mapRecord<K extends string, V, W>(
record: Record<K, V>,
fn: (value: V, key: K) => W
): Record<K, W> {
return Object.fromEntries(
Object.entries(record).map(([k, v]) => [k, fn(v as V, k as K)])
) as Record<K, W>;
}
TypeScript's type system is structural and erased at runtime, but generics exist entirely in the type layer — they impose no runtime cost. The compiler resolves type parameters at each call site through a process called type argument inference, which means callers rarely need to supply explicit type arguments unless inference fails.
Constraints and the extends keyword
extends in a type parameter context means "is assignable to", not class inheritance. <T extends object> accepts any non-primitive. <T extends keyof U> links two parameters. When you constrain, the body gains access to the constraint's members; when unconstrained, the body can only treat T as unknown.
Generic defaults
Type parameter defaults (<T = string>) allow callers to omit the argument. They work like function parameter defaults — the default is used when inference produces unknown or the caller omits it explicitly.
The infer keyword
infer appears only inside conditional type clauses (extends ? T : F). It introduces a fresh type variable that is bound to whatever matched that position in the extends check. Common uses: ReturnType<T>, Parameters<T>, Awaited<T>, and custom extractors.
Variance and type safety
Generic types are covariant in their type parameters by default (not yet formally annotated in TS). This becomes relevant when storing generic values in arrays or returning them from factories — TypeScript widens to the common type unless you keep the parameter in position.
Anti-patterns to avoid
any inside a generic body to make it compile — defeats the purposeidentity<string>("hello") — inference handles this)https://typescriptlang.org/docs/handbook/2/generics.html