typescript
npx skills add https://github.com/dsantiagomj/dsmj-ai-toolkit --skill typescript
Agent 安装分布
Skill 文档
TypeScript – Type-Safe JavaScript
Static typing for JavaScript – works across frontend, backend, and full-stack applications
When to Use This Skill
Use this skill when:
- Writing any JavaScript code that would benefit from type safety
- Building Node.js backend applications
- Developing React, Vue, or other frontend frameworks
- Creating libraries or shared code packages
- Working with APIs and need to define request/response types
- Refactoring existing JavaScript to add type safety
Don’t use this skill when:
- Writing simple scripts where type safety adds no value (config files, build scripts)
- Working with languages other than JavaScript/TypeScript (use their respective skills)
- Types become more complex than the value they provide (prefer simplicity)
Critical Patterns
Pattern 1: Type Inference vs Explicit Types
When: Writing functions and variables
Good:
// â
Let TypeScript infer simple types
const name = 'John' // inferred as string
const age = 30 // inferred as number
const items = [1, 2, 3] // inferred as number[]
// â
Explicit types for function signatures (better docs)
function processUser(id: string, options?: { admin: boolean }): User {
return { id, name: 'John', isAdmin: options?.admin ?? false }
}
// â
Infer return type for simple functions
const double = (n: number) => n * 2 // return type inferred as number
// â
Explicit return type for complex functions
async function fetchUser(id: string): Promise<User | null> {
const response = await fetch(`/api/users/${id}`)
if (!response.ok) return null
return response.json()
}
Bad:
// â Over-annotating obvious types
const name: string = 'John' // unnecessary
const age: number = 30 // unnecessary
// â Missing function parameter types
function processUser(id, options) { // any, any - loses type safety
return { id, name: 'John' }
}
// â Missing return types on exported functions
export function fetchUser(id: string) { // return type unclear
return fetch(`/api/users/${id}`).then(r => r.json())
}
Why: Let TypeScript infer simple types to reduce noise. Add explicit types for function signatures to improve documentation and catch errors.
Pattern 2: Discriminated Unions for Type Safety
When: Handling multiple possible states or types
Good:
// â
Discriminated union with type field
type Result<T> =
| { status: 'success'; data: T }
| { status: 'error'; error: string }
| { status: 'loading' }
function handleResult<T>(result: Result<T>) {
if (result.status === 'success') {
console.log(result.data) // â
TypeScript knows data exists
} else if (result.status === 'error') {
console.log(result.error) // â
TypeScript knows error exists
} else {
console.log('Loading...') // â
TypeScript knows no extra fields
}
}
// â
Discriminated union for different shapes
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rectangle'; width: number; height: number }
| { kind: 'square'; size: number }
function calculateArea(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2
case 'rectangle':
return shape.width * shape.height
case 'square':
return shape.size ** 2
}
}
Bad:
// â Union without discriminator
type Result<T> = {
data?: T
error?: string
loading?: boolean
}
function handleResult<T>(result: Result<T>) {
if (result.data) {
console.log(result.data) // â Could still have error or loading
}
}
Why: Discriminated unions provide exhaustive type checking and make illegal states unrepresentable.
Pattern 3: Generic Constraints for Reusable Code
When: Writing reusable functions that work with multiple types
Good:
// â
Generic with constraints
interface HasId {
id: string
}
function findById<T extends HasId>(items: T[], id: string): T | undefined {
return items.find(item => item.id === id) // â
TypeScript knows T has id
}
// â
keyof constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key] // â
Type-safe property access
}
const user = { name: 'John', age: 30 }
const name = getProperty(user, 'name') // string
const age = getProperty(user, 'age') // number
Bad:
// â Generic without constraints
function findById<T>(items: T[], id: string): T | undefined {
return items.find(item => item.id === id) // â Error: 'id' doesn't exist on T
}
// â Using any loses type safety
function getProperty(obj: any, key: string): any {
return obj[key] // â No type safety
}
Why: Generic constraints ensure type safety while maintaining flexibility.
Pattern 4: Utility Types for Type Transformations
When: Deriving new types from existing ones
Good:
interface User {
id: string
name: string
email: string
password: string
role: 'admin' | 'user'
createdAt: Date
}
// â
Pick for selecting specific properties
type UserPreview = Pick<User, 'id' | 'name'>
// â
Omit for excluding sensitive data
type PublicUser = Omit<User, 'password'>
// â
Partial for optional updates
function updateUser(id: string, updates: Partial<User>) {
// â
Can update any subset of user fields
}
// â
Record for maps/dictionaries
type UserMap = Record<string, User>
const users: UserMap = {
'user1': { id: '1', name: 'John', /* ... */ },
}
// â
ReturnType to extract function return type
function getUser() {
return { id: '1', name: 'John', email: 'john@example.com' }
}
type UserType = ReturnType<typeof getUser>
Bad:
// â Manually duplicating types
type UserPreview = {
id: string // â Duplicated from User
name: string // â Duplicated from User
}
Why: Utility types keep types DRY and automatically sync with source types.
For more examples and patterns, see references/examples.md and references/patterns.md.
Anti-Patterns
â Anti-Pattern 1: Overusing any
Don’t do this:
// â Using any defeats the purpose of TypeScript
function processData(data: any): any {
return data.map((item: any) => item.value)
}
Why it’s bad: Disables TypeScript’s type checking, loses IntelliSense.
Do this instead:
// â
Use specific types or generics
function processData<T extends { value: any }>(data: T[]): any[] {
return data.map(item => item.value)
}
// â
Or use unknown for truly unknown data
function processUnknown(data: unknown) {
if (typeof data === 'string') {
return data.toUpperCase() // â
Type narrowed to string
}
throw new Error('Invalid data')
}
â Anti-Pattern 2: Type Assertions Instead of Type Guards
Don’t do this:
// â Unsafe type assertion
function processUser(data: any) {
const user = data as User // â No runtime check
console.log(user.name.toUpperCase()) // â Runtime error if not a User
}
Why it’s bad: Type assertions bypass type checking and can cause runtime errors.
Do this instead:
// â
Type guards for runtime validation
function isUser(data: unknown): data is User {
return (
typeof data === 'object' &&
data !== null &&
'id' in data &&
'name' in data
)
}
function processUser(data: unknown) {
if (isUser(data)) {
console.log(data.name.toUpperCase()) // â
Type-safe
}
}
â Anti-Pattern 3: Ignoring Strict Mode
Don’t do this:
// tsconfig.json
{
"compilerOptions": {
"strict": false // â Disables all strict checks
}
}
Why it’s bad: Disables TypeScript’s most valuable features.
Do this instead:
// tsconfig.json
{
"compilerOptions": {
"strict": true, // â
Enable all strict checks
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true
}
}
For more anti-patterns and solutions, see references/best-practices.md.
Quick Reference
// Type annotations
let name: string = 'John'
let numbers: number[] = [1, 2, 3]
// Interfaces
interface User {
id: string
name: string
email?: string // Optional
}
// Type aliases
type ID = string | number
type Status = 'idle' | 'loading' | 'success'
// Functions
function add(a: number, b: number): number {
return a + b
}
// Generics
function identity<T>(value: T): T {
return value
}
// Utility types
Partial<T> // All properties optional
Required<T> // All properties required
Readonly<T> // All properties readonly
Pick<T, K> // Select properties
Omit<T, K> // Exclude properties
Record<K, T> // Object with keys K and values T
Learn More
- Examples: references/examples.md – Complete code examples for basic and advanced usage
- Advanced Patterns: references/patterns.md – Mapped types, conditional types, advanced generics
- Configuration: references/configuration.md – tsconfig.json, compiler options
- Advanced Types: references/advanced-types.md – Template literals, branded types
- Best Practices: references/best-practices.md – Code organization, naming conventions
- Node.js Patterns: references/nodejs.md – Express, Prisma, tRPC integration
External References
Maintained by dsmj-ai-toolkit