— No reviews yet
0 installs
17 views
0.0% view→install
Install
$ agentstack add skill-jignesh-ponamwar-skills-mcp-typescript-patterns ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Are you the author of Typescript Patterns? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claimAbout
TypeScript Patterns Skill
1. Strict tsconfig (Always Start Here)
{
"compilerOptions": {
"strict": true, // enables all strict checks
"noUncheckedIndexedAccess": true, // arr[0] returns T | undefined
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"exactOptionalPropertyTypes": true,
"useUnknownInCatchVariables": true,
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
}
}
2. Utility Types - Essential Reference
interface User {
id: number
name: string
email: string
age?: number
}
// Partial - all properties optional
type UpdateUser = Partial
// Required - all properties required
type StrictUser = Required
// Pick - select specific properties
type UserSummary = Pick
// Omit - exclude specific properties
type PublicUser = Omit
// Readonly - prevent mutation
type ImmutableUser = Readonly
// Record - typed object with known key shape
type UserById = Record
type RolePermissions = Record
// Extract / Exclude
type StringOrNumber = string | number | boolean
type OnlyStrNum = Extract // string | number
type NoString = Exclude // number | boolean
// ReturnType / Parameters
function getUser(id: number): Promise { ... }
type GetUserReturn = Awaited> // User
type GetUserParams = Parameters // [id: number]
// NonNullable
type MaybeUser = User | null | undefined
type DefiniteUser = NonNullable // User
3. Generics - Patterns
// Generic function
function first(arr: readonly T[]): T | undefined {
return arr[0]
}
// Generic with constraint
function getProperty(obj: T, key: K): T[K] {
return obj[key]
}
// Generic interface with default
interface ApiResponse {
data: T
status: number
message: string
}
// Multiple type parameters
function merge(a: A, b: B): A & B {
return { ...a, ...b }
}
// Generic class
class Repository {
private items = new Map()
save(item: T): void {
this.items.set(item.id, item)
}
findById(id: number): T | undefined {
return this.items.get(id)
}
findAll(): T[] {
return [...this.items.values()]
}
}
4. Discriminated Unions - Type-Safe State Machines
// Instead of flags (error-prone):
// type Result = { loading: boolean; data?: User; error?: Error }
// Use discriminated union:
type Result =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error }
// TypeScript narrows correctly in each branch:
function renderUser(result: Result) {
switch (result.status) {
case 'idle': return
case 'loading': return
case 'success': return // data is User here
case 'error': return
}
}
// API response pattern
type ApiResult =
| { ok: true; data: T }
| { ok: false; error: string; statusCode: number }
async function fetchUser(id: number): Promise> {
const response = await fetch(`/api/users/${id}`)
if (!response.ok) {
return { ok: false, error: await response.text(), statusCode: response.status }
}
return { ok: true, data: await response.json() }
}
// Consuming:
const result = await fetchUser(1)
if (result.ok) {
console.log(result.data.name) // TypeScript knows data is User
} else {
console.error(result.error) // TypeScript knows error is string
}
5. Branded Types (Nominal Typing)
Prevent mixing up primitive values that have the same underlying type:
// Without brands - easy to mix up IDs:
function getUser(id: number) { ... }
function getOrder(id: number) { ... }
getUser(orderId) // TypeScript allows this - wrong!
// With brands - type-safe:
type UserId = number & { readonly _brand: 'UserId' }
type OrderId = number & { readonly _brand: 'OrderId' }
function createUserId(id: number): UserId {
return id as UserId
}
function getUser(id: UserId) { ... }
function getOrder(id: OrderId) { ... }
const userId = createUserId(123)
const orderId = 456 as OrderId
getUser(userId) // ✅
getUser(orderId) // ❌ TypeScript error - OrderId is not UserId
6. Conditional Types
// Basic conditional type
type IsArray = T extends any[] ? true : false
type Test1 = IsArray // true
type Test2 = IsArray // false
// Infer - extract inner types
type UnwrapPromise = T extends Promise ? U : T
type User = UnwrapPromise> // { name: string }
type ElementType = T extends (infer U)[] ? U : never
type Elem = ElementType // string
// Distributive conditional types
type ToArray = T extends any ? T[] : never
type StringOrNumberArray = ToArray // string[] | number[]
// Non-distributive (wrap in tuple)
type IsUnion = [T] extends [any] ? ([any] extends [T] ? false : true) : false
7. Template Literal Types
type EventName = 'click' | 'focus' | 'blur'
type Handler = `on${Capitalize}` // 'onClick' | 'onFocus' | 'onBlur'
type CSSUnit = 'px' | 'em' | 'rem' | 'vh' | 'vw'
type CSSValue = `${number}${CSSUnit}` // e.g. '16px', '1.5rem'
// Route types
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE'
type ApiRoute = `/api/${string}`
// Extract path parameters
type ExtractParams =
Path extends `${string}:${infer Param}/${infer Rest}`
? Param | ExtractParams
: Path extends `${string}:${infer Param}`
? Param
: never
type Params = ExtractParams // 'id' | 'postId'
8. Type Narrowing
// typeof
function process(value: string | number) {
if (typeof value === 'string') {
return value.toUpperCase() // string here
}
return value * 2 // number here
}
// instanceof
function handleError(err: unknown): string {
if (err instanceof Error) return err.message
if (typeof err === 'string') return err
return 'Unknown error'
}
// User-defined type guard
interface Cat { meow(): void }
interface Dog { bark(): void }
function isCat(animal: Cat | Dog): animal is Cat {
return 'meow' in animal
}
// Assertion function
function assertDefined(value: T, name: string): asserts value is NonNullable {
if (value === null || value === undefined) {
throw new Error(`Expected ${name} to be defined`)
}
}
9. Eliminating any
// ❌ any - unsafe
function parseData(raw: any) {
return raw.user.name // runtime error if shape wrong
}
// ✅ unknown + narrowing - safe
function parseData(raw: unknown): string {
if (
typeof raw === 'object' && raw !== null &&
'user' in raw && typeof (raw as any).user === 'object' &&
'name' in (raw as any).user
) {
return String((raw as any).user.name)
}
throw new Error('Unexpected data shape')
}
// ✅ Zod - best for runtime validation of external data
import { z } from 'zod'
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
})
type User = z.infer
const user = UserSchema.parse(rawData) // throws on invalid, returns User
Common Mistakes
- Using
anyinstead ofunknown-unknownforces narrowing before use aseverywhere -as SomeTypesuppresses errors; use type guards instead!non-null assertion without checking - assert only when you've verified the value exists- Loose
tsconfig- always start with"strict": true - Interface vs type for objects - prefer
interfacefor public APIs (extensible),typefor unions and computed types - Forgetting
readonly- immutable arrays should usereadonly T[]notT[] - Implicit
anyin catch - usecatch (err: unknown)and narrow toErrorbefore accessing.message
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Jignesh-Ponamwar
- Source: Jignesh-Ponamwar/skills-mcp
- License: Apache-2.0
- Homepage: https://skills-mcp-jignesh.vercel.app/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.