Claude-skill-registry-data mastering-typescript
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry-data
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/mastering-typescript" ~/.claude/skills/majiayu000-claude-skill-registry-data-mastering-typescript && rm -rf "$T"
manifest:
data/mastering-typescript/SKILL.mdsource content
Mastering Modern TypeScript
Build enterprise-grade, type-safe applications with TypeScript 5.9+.
Compatibility: TypeScript 5.9+, Node.js 22 LTS, Vite 7, NestJS 11, React 19
Quick Start
# Initialize TypeScript project with ESM pnpm create vite@latest my-app --template vanilla-ts cd my-app && pnpm install # Configure strict TypeScript cat > tsconfig.json << 'EOF' { "compilerOptions": { "target": "ES2024", "module": "ESNext", "moduleResolution": "bundler", "strict": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "esModuleInterop": true, "skipLibCheck": true } } EOF
When to Use This Skill
Use when:
- Building type-safe React, NestJS, or Node.js applications
- Migrating JavaScript codebases to TypeScript
- Implementing advanced type patterns (generics, mapped types, conditional types)
- Configuring modern TypeScript toolchains (Vite, pnpm, ESLint)
- Designing type-safe API contracts with Zod validation
- Comparing TypeScript approaches with Java or Python
Project Setup Checklist
Before starting any TypeScript project:
- [ ] Use pnpm for package management (faster, disk-efficient) - [ ] Configure ESM-first (type: "module" in package.json) - [ ] Enable strict mode in tsconfig.json - [ ] Set up ESLint with @typescript-eslint - [ ] Add Prettier for consistent formatting - [ ] Configure Vitest for testing
Type System Quick Reference
Primitive Types
const name: string = "Alice"; const age: number = 30; const active: boolean = true; const id: bigint = 9007199254740991n; const key: symbol = Symbol("unique");
Union and Intersection Types
// Union: value can be one of several types type Status = "pending" | "approved" | "rejected"; // Intersection: value must satisfy all types type Employee = Person & { employeeId: string }; // Discriminated union for type-safe handling type Result<T> = | { success: true; data: T } | { success: false; error: string }; function handleResult<T>(result: Result<T>): T | null { if (result.success) { return result.data; // TypeScript knows data exists here } console.error(result.error); return null; }
Type Guards
// typeof guard function process(value: string | number): string { if (typeof value === "string") { return value.toUpperCase(); } return value.toFixed(2); } // Custom type guard interface User { type: "user"; name: string } interface Admin { type: "admin"; permissions: string[] } function isAdmin(person: User | Admin): person is Admin { return person.type === "admin"; }
The satisfies
Operator (TS 5.0+)
satisfiesValidate type conformance while preserving inference:
// Problem: Type assertion loses specific type info const colors1 = { red: "#ff0000", green: "#00ff00" } as Record<string, string>; colors1.red.toUpperCase(); // OK, but red could be undefined // Solution: satisfies preserves literal types const colors2 = { red: "#ff0000", green: "#00ff00" } satisfies Record<string, string>; colors2.red.toUpperCase(); // OK, and TypeScript knows red exists
Generics Patterns
Basic Generic Function
function first<T>(items: T[]): T | undefined { return items[0]; } const num = first([1, 2, 3]); // number | undefined const str = first(["a", "b"]); // string | undefined
Constrained Generics
interface HasLength { length: number; } function logLength<T extends HasLength>(item: T): T { console.log(item.length); return item; } logLength("hello"); // OK: string has length logLength([1, 2, 3]); // OK: array has length logLength(42); // Error: number has no length
Generic API Response Wrapper
interface ApiResponse<T> { data: T; status: number; timestamp: Date; } async function fetchUser(id: string): Promise<ApiResponse<User>> { const response = await fetch(`/api/users/${id}`); const data = await response.json(); return { data, status: response.status, timestamp: new Date() }; }
Utility Types Reference
| Type | Purpose | Example |
|---|---|---|
| All properties optional | |
| All properties required | |
| Select specific properties | |
| Exclude specific properties | |
| Object with typed keys/values | |
| Extract function return type | |
| Extract function parameters | |
| Unwrap Promise type | |
Conditional Types
// Basic conditional type type IsString<T> = T extends string ? true : false; // Extract array element type type ArrayElement<T> = T extends (infer E)[] ? E : never; type Numbers = ArrayElement<number[]>; // number type Strings = ArrayElement<string[]>; // string // Practical: Extract Promise result type type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;
Mapped Types
// Make all properties readonly type Immutable<T> = { readonly [K in keyof T]: T[K]; }; // Make all properties nullable type Nullable<T> = { [K in keyof T]: T[K] | null; }; // Create getter functions for each property type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]; }; interface Person { name: string; age: number } type PersonGetters = Getters<Person>; // { getName: () => string; getAge: () => number }
Framework Integration
React with TypeScript
// Typed functional component interface ButtonProps { label: string; onClick: () => void; variant?: "primary" | "secondary"; } const Button: React.FC<ButtonProps> = ({ label, onClick, variant = "primary" }) => ( <button className={variant} onClick={onClick}> {label} </button> ); // Typed hooks const [count, setCount] = useState<number>(0); const userRef = useRef<HTMLInputElement>(null);
NestJS with TypeScript
// Type-safe DTO with class-validator import { IsString, IsEmail, MinLength } from 'class-validator'; class CreateUserDto { @IsString() @MinLength(2) name: string; @IsEmail() email: string; } // Or with Zod (modern approach) import { z } from 'zod'; const CreateUserSchema = z.object({ name: z.string().min(2), email: z.string().email() }); type CreateUserDto = z.infer<typeof CreateUserSchema>;
See react-integration.md and nestjs-integration.md for detailed patterns.
Validation with Zod
import { z } from 'zod'; // Define schema const UserSchema = z.object({ id: z.string().uuid(), name: z.string().min(1).max(100), email: z.string().email(), role: z.enum(["user", "admin", "moderator"]), createdAt: z.coerce.date() }); // Infer TypeScript type from schema type User = z.infer<typeof UserSchema>; // Validate at runtime function parseUser(data: unknown): User { return UserSchema.parse(data); // Throws ZodError if invalid } // Safe parsing (returns result object) const result = UserSchema.safeParse(data); if (result.success) { console.log(result.data); // Typed as User } else { console.error(result.error.issues); }
Modern Toolchain (2025)
| Tool | Version | Purpose |
|---|---|---|
| TypeScript | 5.9+ | Type checking and compilation |
| Node.js | 22 LTS | Runtime environment |
| Vite | 7.x | Build tool and dev server |
| pnpm | 9.x | Package manager |
| ESLint | 9.x | Linting with flat config |
| Vitest | 3.x | Testing framework |
| Prettier | 3.x | Code formatting |
ESLint Flat Config (ESLint 9+)
// eslint.config.js import eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.strictTypeChecked, { languageOptions: { parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname, }, }, } );
Migration Strategies
Incremental Migration
- Add
andallowJs: true
to tsconfig.jsoncheckJs: false - Rename files from
to.js
one at a time.ts - Add type annotations gradually
- Enable stricter options incrementally
JSDoc for Gradual Typing
// Before full migration, use JSDoc /** * @param {string} name * @param {number} age * @returns {User} */ function createUser(name, age) { return { name, age }; }
See enterprise-patterns.md for comprehensive migration guides.
Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
Using liberally | Defeats type safety | Use and narrow |
| Ignoring strict mode | Misses null/undefined bugs | Enable all strict options |
Type assertions () | Can hide type errors | Use or guards |
| Enum for simple unions | Generates runtime code | Use literal unions instead |
| Not validating API data | Runtime type mismatches | Use Zod at boundaries |
Cross-Language Comparison
| Feature | TypeScript | Java | Python |
|---|---|---|---|
| Type System | Structural | Nominal | Gradual (duck typing) |
| Nullability | Explicit () | annotations | Optional via typing |
| Generics | Type-level, erased | Type-level, erased | Runtime via typing |
| Interfaces | Structural matching | Must implement | Protocol (3.8+) |
| Enums | Avoid (use unions) | First-class | Enum class |
Reference Files
- type-system.md — Complete type system guide
- generics.md — Advanced generics patterns
- enterprise-patterns.md — Error handling, validation, architecture
- react-integration.md — React + TypeScript patterns
- nestjs-integration.md — NestJS API development
- toolchain.md — Modern build tools configuration
Assets
- tsconfig-template.json — Strict enterprise config
- eslint-template.js — ESLint 9 flat config
Scripts
- validate-setup.sh — Verify TypeScript environment