typescript-patterns
Skill0 starsChanged 5 months agoMITView on GitHub
TypeScript type-system patterns — generics, conditional and utility types, strict mode, discriminated unions, type guards, and ecosystem idioms (Zod/Valibot). Use when modeling types, tightening strictness, or untangling complex generics.
8 other projects use a version of this.
Adopted by
Most recently taken up by
- MMACABRE/SKILLStheir own version, first seen Nov 8, 2026
- reddygopalkrishna/developer-agent-skillstheir own version, first seen Nov 8, 2026
- ku5ic/claude-kittheir own version, first seen Nov 4, 2026
- sabahattink/antigravity-fullstack-hqtheir own version, first seen Sep 20, 2026
- techmefr/mentistheir own version, first seen Sep 11, 2026
- bjornjee/skillstheir own version, first seen Sep 8, 2026
Used with
Projects with it also use fastapi-patterns, react-patterns and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
seikaikyoSkillfastapi-patterns
FastAPI + SQLModel + Neon PostgreSQL 後端開發最佳實踐。適用於 Render 部署的 API 服務。涵蓋路由設計、資料庫操作、錯誤處理、認證授權。
Also in 3 projects that use this
xenitV1Skillreact-patterns
Modern React patterns and principles. Hooks, composition, performance, TypeScript best practices.
Also in 3 projects that use this
xenitV1Skillpython-patterns
Python development principles and decision-making. Framework selection, async patterns, type hints, project structure. Teaches thinking, not copying.
Also in 3 projects that use this
Other versions8 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 8
- cohen-liel/hivemind★ 108same name
- sabahattink/antigravity-fullstack-hq★ 30same name
- reddygopalkrishna/developer-agent-skills★ 8same name
- peopleforrester/claude-dotfiles★ 3same name
- bjornjee/skills★ 2same name
- ku5ic/claude-kit★ 2same name
- MMACABRE/SKILLS★ 1same name
- techmefr/mentis★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository20 other files it gives its agents.
- context-engineeringSkill
- multi-agent-patternsSkill
- prompt-injection-defenseSkill
- rag-retrievalSkill
- adr-writerSkill
- ci-cdSkill
- playwright-e2eSkill
- structural-searchSkill
- react-server-componentsSkill
- shadcn-uiSkill
- tailwind-v4Skill
- zustand-stateSkill
- accessibilitySkill
- api-designSkill
- database-patternsSkill
- debuggingSkill
- security-patternsSkill
- proposal-writerSkill
- task-prioritizationSkill
- sitecore-xmcloudSkill
The file
Files
TypeScript Operations
Comprehensive TypeScript skill covering the type system, generics, and production patterns.
Type Narrowing Decision Tree
How to narrow a type?
│
├─ Primitive type check
│ └─ typeof: typeof x === "string"
│
├─ Instance check
│ └─ instanceof: x instanceof Date
│
├─ Property existence
│ └─ in: "email" in user
│
├─ Discriminated union
│ └─ switch on literal field: switch (event.type)
│
├─ Null/undefined check
│ └─ Truthiness: if (x) or if (x != null)
│
├─ Custom logic
│ └─ Type predicate: function isUser(x: unknown): x is User
│
└─ Assertion (you know better than TS)
└─ as: value as string (escape hatch, avoid when possible)Type Guard Example
interface Dog { bark(): void; breed: string }
interface Cat { meow(): void; color: string }
function isDog(pet: Dog | Cat): pet is Dog {
return "bark" in pet;
}
function handlePet(pet: Dog | Cat) {
if (isDog(pet)) {
pet.bark(); // TS knows it's Dog here
} else {
pet.meow(); // TS knows it's Cat here
}
}Discriminated Unions
type Result<T> =
| { status: "success"; data: T }
| { status: "error"; error: string }
| { status: "loading" };
function handle<T>(result: Result<T>) {
switch (result.status) {
case "success": return result.data; // data is available
case "error": throw new Error(result.error); // error is available
case "loading": return null;
}
// Exhaustiveness check: result is `never` here
const _exhaustive: never = result;
}Utility Types Cheat Sheet
| Utility | What It Does | Example |
Partial<T> | All props optional | Partial<User> for update payloads |
Required<T> | All props required | Required<Config> for validated config |
Readonly<T> | All props readonly | Readonly<State> for immutable state |
Pick<T, K> | Select specific props | Pick<User, "id" | "name"> |
Omit<T, K> | Remove specific props | Omit<User, "password"> |
Record<K, V> | Object with typed keys/values | Record<string, number> |
Exclude<U, E> | Remove types from union | Exclude<Status, "deleted"> |
Extract<U, E> | Keep types from union | Extract<Event, { type: "click" }> |
NonNullable<T> | Remove null/undefined | NonNullable<string | null> |
ReturnType<F> | Function return type | ReturnType<typeof fetchUser> |
Parameters<F> | Function params as tuple | Parameters<typeof createUser> |
Awaited<T> | Unwrap Promise type | Awaited<Promise<User>> = User |
Generic Patterns
Constrained Generics
// Basic constraint
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 generic type
type ApiResponse<T = unknown> = {
data: T;
status: number;
};Conditional Types
// Basic conditional
type IsString<T> = T extends string ? true : false;
// infer keyword - extract inner type
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type UnwrapArray<T> = T extends (infer U)[] ? U : T;
// Distributive conditional (distributes over union)
type ToArray<T> = T extends any ? T[] : never;
// ToArray<string | number> = string[] | number[]
// Prevent distribution with wrapping
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;
// ToArrayNonDist<string | number> = (string | number)[]Mapped Types
// Make all properties optional and nullable
type Nullable<T> = { [K in keyof T]: T[K] | null };
// Add prefix to keys
type Prefixed<T, P extends string> = {
[K in keyof T as `${P}${Capitalize<string & K>}`]: T[K];
};
// Prefixed<{ name: string }, "get"> = { getName: string }
// Filter keys by value type
type StringKeys<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};Deep dive: Load ./references/generics-patterns.md for advanced type-level programming, recursive types, template literal types.
tsconfig Quick Reference
{
"compilerOptions": {
// Strict mode (always enable)
"strict": true, // Enables all strict checks
"noUncheckedIndexedAccess": true, // arr[0] is T | undefined
// Module system
"module": "esnext", // or "nodenext" for Node
"moduleResolution": "bundler", // or "nodenext"
"esModuleInterop": true,
// Output
"target": "es2022",
"outDir": "dist",
"declaration": true, // Generate .d.ts
"sourceMap": true,
// Paths
"baseUrl": ".",
"paths": { "@/*": ["src/*"] },
// Strictness extras
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}Deep dive: Load ./references/config-strict.md for strict mode migration, monorepo config, project references.
Common Gotchas
| Gotcha | Why | Fix |
any leaks | any disables type checking for everything it touches | Use unknown + narrowing instead |
as assertions hide bugs | Assertion doesn't check at runtime | Use type guards or validation (Zod) |
enum quirks | Numeric enums are not type-safe, reverse mappings confuse | Use as const objects or string literal unions |
object vs Record vs {} | {} matches any non-null value, object is non-primitive | Use Record<string, unknown> for "any object" |
| Array index access | arr[999] returns T not T | undefined by default | Enable noUncheckedIndexedAccess |
| Optional vs undefined | { x?: string } allows missing key, { x: string | undefined } requires key | Be explicit about which you mean |
! non-null assertion | Silences null checks, no runtime effect | Use ?? defaultValue or proper null check |
| Structural typing surprise | { a: 1, b: 2 } assignable to { a: number } | Use branded types for nominal typing |
Branded / Nominal Types
// Prevent accidentally mixing types that are structurally identical
type UserId = string & { readonly __brand: "UserId" };
type OrderId = string & { readonly __brand: "OrderId" };
function createUserId(id: string): UserId { return id as UserId; }
function getUser(id: UserId) { /* ... */ }
const userId = createUserId("u-123");
const orderId = "o-456" as OrderId;
getUser(userId); // OK
getUser(orderId); // Error: OrderId not assignable to UserIdRuntime Validation (Zod)
import { z } from "zod";
// Define schema
const UserSchema = z.object({
id: z.number(),
name: z.string().min(1),
email: z.string().email(),
role: z.enum(["admin", "user"]),
settings: z.object({
theme: z.enum(["light", "dark"]).default("light"),
}).optional(),
});
// Infer type from schema
type User = z.infer<typeof UserSchema>;
// Validate
const user = UserSchema.parse(untrustedData); // throws on invalid
const result = UserSchema.safeParse(untrustedData); // returns { success, data/error }Reference Files
Load these for deep-dive topics. Each is self-contained.
| Reference | When to Load |
./references/type-system.md | Advanced types, branded types, type-level programming, satisfies operator |
./references/generics-patterns.md | Generic constraints, conditional types, mapped types, template literals, recursive types |
./references/utility-types.md | All built-in utility types with examples, custom utility types |
./references/config-strict.md | tsconfig deep dive, strict mode migration, project references, monorepo setup |
./references/ecosystem.md | Zod/Valibot, type-safe API clients, ORM types, testing with Vitest |
See Also
testing-ops- Cross-language testing strategiesci-cd-ops- TypeScript CI pipelines, type checking in CI
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

