typescript-pro
SKILL.md
TypeScript Pro
Guidelines for advanced TypeScript typing and enterprise-grade development.
Core Principles
- Strict mode always - Enable all strict checks
- Infer when clear - Let TypeScript infer obvious types
- Generic constraints - Use
extendsto constrain generics - Discriminated unions - For type-safe state machines
- Utility types - Leverage built-in and custom utilities
Strict TSConfig
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true,
"moduleResolution": "bundler",
"module": "ESNext",
"target": "ES2022",
"lib": ["ES2022", "DOM"],
"skipLibCheck": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
}
}
Advanced Generics
Constrained Generics
// Constrain to objects with specific shape
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
// Multiple constraints
function merge<T extends object, U extends object>(a: T, b: U): T & U {
return { ...a, ...b };
}
// Default type parameters
function createState<T = unknown>(initial: T): State<T> {
return { value: initial, set: (v: T) => { } };
}
Conditional Types
// Extract return type of async functions
type Awaited<T> = T extends Promise<infer U> ? U : T;
// Make specific properties optional
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
// Extract function parameters
type FirstArg<F> = F extends (arg: infer A, ...args: any[]) => any ? A : never;
// Deep readonly
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
Template Literal Types
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Endpoint = `/api/${string}`;
type Route = `${HTTPMethod} ${Endpoint}`;
// Event handlers
type EventName = 'click' | 'focus' | 'blur';
type Handler = `on${Capitalize<EventName>}`;
// Result: 'onClick' | 'onFocus' | 'onBlur'
// Path parameters
type ExtractParams<T extends string> =
T extends `${string}:${infer Param}/${infer Rest}`
? Param | ExtractParams<Rest>
: T extends `${string}:${infer Param}`
? Param
: never;
type Params = ExtractParams<'/users/:id/posts/:postId'>;
// Result: 'id' | 'postId'
Discriminated Unions
State Machines
type RequestState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
function handleState<T>(state: RequestState<T>) {
switch (state.status) {
case 'idle':
return 'Ready';
case 'loading':
return 'Loading...';
case 'success':
return state.data; // TypeScript knows data exists
case 'error':
return state.error.message; // TypeScript knows error exists
}
}
Exhaustive Checks
function assertNever(x: never): never {
throw new Error(`Unexpected value: ${x}`);
}
type Shape = { kind: 'circle'; radius: number }
| { kind: 'square'; side: number };
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'square':
return shape.side ** 2;
default:
return assertNever(shape); // Compile error if cases missed
}
}
Utility Types
Built-in Utilities
// Partial<T> - all properties optional
// Required<T> - all properties required
// Readonly<T> - all properties readonly
// Record<K, V> - object with keys K and values V
// Pick<T, K> - subset of properties
// Omit<T, K> - exclude properties
// Exclude<T, U> - exclude types from union
// Extract<T, U> - extract types from union
// NonNullable<T> - remove null and undefined
// ReturnType<F> - return type of function
// Parameters<F> - parameter types as tuple
// Awaited<T> - unwrap Promise type
Custom Utility Types
// Make all properties mutable
type Mutable<T> = {
-readonly [K in keyof T]: T[K];
};
// Require at least one of the specified keys
type RequireAtLeastOne<T, Keys extends keyof T = keyof T> =
Pick<T, Exclude<keyof T, Keys>> &
{ [K in Keys]: Required<Pick<T, K>> }[Keys];
// Exact type (no extra properties)
type Exact<T, U extends T> = T & Record<Exclude<keyof U, keyof T>, never>;
// Deep partial
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
Type Guards
// Type predicates
function isString(value: unknown): value is string {
return typeof value === 'string';
}
// Assertion functions
function assertDefined<T>(value: T | null | undefined): asserts value is T {
if (value === null || value === undefined) {
throw new Error('Value is not defined');
}
}
// Usage
const data: string | null = getData();
assertDefined(data);
// data is now string (not string | null)
Branded Types
// Nominal typing via branding
type Brand<T, B> = T & { __brand: B };
type UserId = Brand<string, 'UserId'>;
type OrderId = Brand<string, 'OrderId'>;
function getUser(id: UserId): User { }
const userId = 'abc' as UserId;
const orderId = 'xyz' as OrderId;
getUser(userId); // OK
getUser(orderId); // Error: OrderId not assignable to UserId
Function Overloads
// Overloads for different return types based on input
function parse(input: string): object;
function parse(input: string, asArray: true): unknown[];
function parse(input: string, asArray?: boolean): object | unknown[] {
const result = JSON.parse(input);
return asArray ? (Array.isArray(result) ? result : [result]) : result;
}
Module Augmentation
// Extend existing module types
declare module 'express' {
interface Request {
user?: { id: string; role: string };
}
}
// Global augmentation
declare global {
interface Window {
analytics: Analytics;
}
}
Common Patterns
Builder Pattern
class QueryBuilder<T extends object> {
private query: Partial<T> = {};
where<K extends keyof T>(key: K, value: T[K]): this {
this.query[key] = value;
return this;
}
build(): Partial<T> {
return { ...this.query };
}
}
Result Type
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
function ok<T>(value: T): Result<T, never> {
return { ok: true, value };
}
function err<E>(error: E): Result<never, E> {
return { ok: false, error };
}
Weekly Installs
2
Repository
arosenkranz/cla…e-configGitHub Stars
1
First Seen
14 days ago
Security Audits
Installed on
cline2
gemini-cli2
github-copilot2
codex2
kimi-cli2
cursor2