Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Typescript Advanced Patterns

ASecurity

Advanced TypeScript type system patterns for production codebases. [What: branded types for nominal typing, discriminated unions, template literal types, conditional types, the infer keyword, satisfies operator, const assertions, Zod schema inference, type-safe event emitters, exhaustive switch checking] [When: designing domain models, building type-safe APIs, creating reusable generic utilities, eliminating runtime bugs with compile-time guarantees, refactoring any-typed codebases] [Keywords...

2 stars
0 votes
0 copies
1 views
Added 9/24/2026
developmenttypescriptgobashreactnodetestingrefactoringapidatabaseperformance

Works with

cliapi

Security Analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned 9/24/2026

$npx -y skills add curiositech/port-daddy --skill typescript-advanced-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Typescript Advanced Patterns?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Typescript Advanced Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/curiositech-typescript-advanced-patterns-port-daddy/badge)](https://www.skillsdirectory.com/skills/curiositech-typescript-advanced-patterns-port-daddy)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
license: Apache-2.0
name: typescript-advanced-patterns
description: 'Advanced TypeScript type system patterns for production codebases. [What: branded types for nominal typing, discriminated unions, template literal types, conditional types, the infer keyword, satisfies operator, const assertions, Zod schema inference, type-safe event emitters, exhaustive switch checking] [When: designing domain models, building type-safe APIs, creating reusable generic utilities, eliminating runtime bugs with compile-time guarantees, refactoring any-typed codebases] [Keywords: branded types, discriminated union, template literal types, conditional types, infer, satisfies, const assertion, Zod inference, exhaustive, mapped types, utility types, nominal typing, type narrowing, generic constraints] NOT for basic TypeScript syntax or React component typing (use a React-specific skill).'
allowed-tools: Read,Write,Edit,Bash(npm:*,npx:*,tsc:*)
argument-hint: '[problem type: nominal-typing|discriminated-union|type-safe-events|zod-inference|conditional-types]'
metadata:
  category: Code Quality & Testing
  pairs-with:
    - skill: api-architect
      reason: Type-safe API contracts with Zod
    - skill: vitest-testing-patterns
      reason: Type-level testing with expect-type
    - skill: react-performance-optimizer
      reason: Type-safe React patterns
  tags:
    - typescript
    - type-system
    - branded-types
    - generics
    - zod
category: Code Quality & Testing
tags:
  - typescript
  - advanced-patterns
  - generics
  - type-system
  - best-practices
---

# TypeScript Advanced Patterns

Advanced type system patterns that eliminate runtime bugs by encoding constraints at compile time.

## DECISION POINTS

### Problem → Pattern Selection Tree

```
1. Are you mixing values of the same primitive type?
   ├─ YES: ID confusion (UserId vs OrderId) → Use Branded Types
   ├─ YES: Money confusion (USD vs EUR, dollars vs cents) → Use Branded Types with validation
   └─ NO: Continue to #2

2. Do you have a value that can be one of N different shapes?
   ├─ YES: API responses (success/error/loading) → Use Discriminated Unions
   ├─ YES: State machine states → Use Discriminated Unions with exhaustive checking
   └─ NO: Continue to #3

3. Are you parsing external data (APIs, user input)?
   ├─ YES: Unknown JSON shape → Use Zod schema + z.infer<typeof Schema>
   ├─ YES: Form validation → Use Zod with branded types for validated inputs
   └─ NO: Continue to #4

4. Do you need types that compute based on other types?
   ├─ YES: Extract function parameters → Use conditional types with infer
   ├─ YES: Transform object shapes → Use mapped types with template literals
   └─ NO: Continue to #5

5. Are you validating without losing specific type info?
   ├─ YES: Config objects with optional fields → Use satisfies operator
   ├─ YES: Const arrays that need narrow types → Use const assertions
   └─ NO: Review if advanced patterns are needed
```

### Implementation Strategy Decision

```
IF (primitive mixing bugs possible)
  → Start with branded types for domain IDs
  → Add Zod constructors for validation

IF (multiple related states)
  → Define discriminated union with 'kind'/'type'/'status' field
  → Add exhaustive switch with assertNever default

IF (external data + type safety needed)
  → Define Zod schema first
  → Export type as z.infer<typeof Schema>
  → Never manually write types for external data

IF (generic utilities needed)
  → Use conditional types with infer for extraction
  → Add constraints to prevent misuse
  → Test with expect-type for complex utilities
```

## FAILURE MODES

### 1. Over-Branding Primitives
**Symptom**: Every string and number in codebase is branded
**Detection**: If you see `Brand<string, 'FirstName'>` and `Brand<string, 'LastName'>` that are never mixed up
**Root Cause**: Treating branding as general "make types stricter" instead of "prevent specific mixing bugs"
**Fix**: Only brand when there's actual confusion risk (IDs, money, different units)

### 2. Schema Bloat Anti-Pattern
**Symptom**: Zod schemas with 50+ fields, nested 5+ levels deep
**Detection**: Schema definitions longer than the components that use them
**Root Cause**: Trying to validate entire API response instead of just the fields you use
**Fix**: Parse only what you need - `z.object({ id: z.string(), status: z.enum(['active', 'inactive']) })` instead of full user object

### 3. Type Assertion Abuse
**Symptom**: Multiple `as Type` casts or `as any` to make TypeScript "stop complaining"
**Detection**: More than 2 type assertions in a single function
**Root Cause**: Fighting the type system instead of designing types that match data flow
**Fix**: Use type guards, Zod parsing, or unknown with proper narrowing

### 4. Discriminant Field Inconsistency
**Symptom**: Union types work in some places but not others, "Property does not exist" errors
**Detection**: TypeScript can't narrow the union in switch statements
**Root Cause**: Discriminant field missing or inconsistent across union members
**Fix**: Every union member must have same discriminant field with literal type

### 5. Incorrect Union Discriminants
**Symptom**: TypeScript allows invalid state combinations like `{ status: 'success', error: string }`
**Detection**: Properties from wrong union branch are accessible
**Root Cause**: Discriminant field values overlap or missing literal types
**Fix**: Use non-overlapping literal types in discriminant field, validate each branch is exclusive

## WORKED EXAMPLES

### Example 1: Refactoring any-typed API Response to Discriminated Union

**Starting Point**: Legacy API client with any types
```typescript
// Before: any everywhere, runtime errors common
async function fetchUser(id: string): Promise<any> {
  const response = await fetch(`/api/users/${id}`);
  return response.json(); // any
}

// Usage leads to runtime errors
const userData = await fetchUser('123');
console.log(userData.user.profile.name); // Works sometimes, crashes others
```

**Step 1: Analyze actual API responses** (what novice skips)
```typescript
// Expert examines actual responses first:
// Success: { status: 'success', user: { id: string, name: string } }
// Not found: { status: 'error', code: 404, message: 'User not found' }
// Server error: { status: 'error', code: 500, message: 'Internal error' }
```

**Step 2: Define discriminated union** (novice would create separate types)
```typescript
type ApiResponse<T> = 
  | { status: 'success'; data: T }
  | { status: 'error'; code: number; message: string };

type User = {
  id: string;
  name: string;
  email: string;
};
```

**Step 3: Create Zod schema** (expert validates at runtime boundary)
```typescript
import { z } from 'zod';

const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
});

const ApiResponseSchema = <T extends z.ZodType>(dataSchema: T) =>
  z.discriminatedUnion('status', [
    z.object({
      status: z.literal('success'),
      data: dataSchema,
    }),
    z.object({
      status: z.literal('error'),
      code: z.number(),
      message: z.string(),
    }),
  ]);

type ApiResponse<T> = z.infer<ReturnType<typeof ApiResponseSchema>>;
```

**Step 4: Type-safe client** (novice forgets error handling)
```typescript
async function fetchUser(id: string): Promise<ApiResponse<User>> {
  const response = await fetch(`/api/users/${id}`);
  const rawData: unknown = await response.json();
  
  // Parse with Zod - throws on invalid shape
  return ApiResponseSchema(UserSchema).parse(rawData);
}

// Usage forces error handling
const userResult = await fetchUser('123');
switch (userResult.status) {
  case 'success':
    console.log(userResult.data.name); // TypeScript knows data exists
    break;
  case 'error':
    console.error(`Error ${userResult.code}: ${userResult.message}`);
    break;
}
```

**Trade-offs expert considers** (novice misses):
- Runtime cost: Zod validation adds ~5ms per parse
- Bundle size: Zod adds ~14KB gzipped
- Developer experience: Immediate errors vs silent runtime failures
- Maintenance: Schema evolution vs type drift

## QUALITY GATES

- [ ] All primitive domain values that could be mixed are branded (UserId ≠ OrderId)
- [ ] No bare `any` types - use `unknown` at boundaries with proper narrowing
- [ ] External data parsed through Zod schemas, never assumed to match types
- [ ] Union types use discriminated unions with exhaustive switch checking
- [ ] Type assertions (`as Type`) used only for proven safe narrows, never `as any`
- [ ] Conditional types include TSDoc comment explaining their purpose
- [ ] Complex utility types have expect-type tests verifying behavior
- [ ] satisfies operator used for config objects instead of widening type annotations
- [ ] Generic constraints are as specific as needed (`T extends object` not `T extends any`)
- [ ] All branded type constructors include validation logic

## NOT-FOR Boundaries

**Don't use for:**
- Basic type annotations (`string`, `number[]`, `{ name: string }`)
- React component prop typing → Use `react-component-patterns` skill instead
- Node.js API client typing → Use `api-architect` skill for OpenAPI generation
- Database query typing → Use ORM-specific skills (Prisma, Drizzle)
- GraphQL schema typing → Use `graphql-typescript` skill for codegen

**Delegate to other skills when:**
- Building REST APIs → Use `api-architect` for contract-first design
- Testing type-level behavior → Use `vitest-testing-patterns` for expect-type tests
- Performance optimization → Use `react-performance-optimizer` for memo patterns
- Error boundary patterns → Use `error-handling-strategies` for Result types
## Imported bundle navigation

These preserved source files add depth when their stated topic is needed.

- [references/branded-types.md](references/branded-types.md) — Branded Types Reference.
- [references/type-safe-patterns.md](references/type-safe-patterns.md) — Type-Safe Patterns Reference.

Attribution

curiositechcuriositech
View sourceSee grades on GitHubMore from curiositech →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

286712 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Writing Plans

Use when you have a spec or requirements for a multi-step task, before touching code

2927051 votes
View all in development →