
Javascript Typescript
- 73 installs
- 19 repo stars
- Updated January 20, 2026
- miles990/claude-software-skills
Helps with ai & agent building tasks.
About
javascript-typescript is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- javascript-typescript
- AI & Agent Building
- AI-coding skill
Javascript Typescript by the numbers
- 73 all-time installs (skills.sh)
- +2 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #5,587 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/miles990/claude-software-skills --skill javascript-typescriptAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 73 |
|---|---|
| repo stars | ★ 19 |
| Last updated | January 20, 2026 |
| Repository | miles990/claude-software-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
JavaScript & TypeScript
Overview
Modern JavaScript (ES6+) and TypeScript patterns for building robust applications.
---
TypeScript Fundamentals
Type Definitions
// Basic types
type UserId = string;
type Timestamp = number;
// Object types
interface User {
id: UserId;
email: string;
name: string;
createdAt: Timestamp;
metadata?: Record<string, unknown>;
}
// Union types
type Status = 'pending' | 'active' | 'inactive';
// Discriminated unions
type Result<T, E = Error> =
| { success: true; data: T }
| { success: false; error: E };
// Generic types
interface Repository<T extends { id: string }> {
find(id: string): Promise<T | null>;
findAll(filter?: Partial<T>): Promise<T[]>;
create(data: Omit<T, 'id'>): Promise<T>;
update(id: string, data: Partial<T>): Promise<T>;
delete(id: string): Promise<void>;
}
// Utility types
type CreateUserInput = Omit<User, 'id' | 'createdAt'>;
type UpdateUserInput = Partial<Pick<User, 'name' | 'metadata'>>;
type UserKeys = keyof User;
// Conditional types
type Nullable<T> = T | null;
type NonNullableFields<T> = {
[K in keyof T]-?: NonNullable<T[K]>;
};
// Template literal types
type EventName = `on${Capitalize<string>}`;
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type ApiRoute = `/${string}`;Type Guards
// Type predicates
function isUser(obj: unknown): obj is User {
return (
typeof obj === 'object' &&
obj !== null &&
'id' in obj &&
'email' in obj &&
typeof (obj as User).id === 'string'
);
}
// Discriminated union guards
interface Dog {
kind: 'dog';
bark(): void;
}
interface Cat {
kind: 'cat';
meow(): void;
}
type Animal = Dog | Cat;
function handleAnimal(animal: Animal) {
switch (animal.kind) {
case 'dog':
animal.bark(); // TypeScript knows this is Dog
break;
case 'cat':
animal.meow(); // TypeScript knows this is Cat
break;
}
}
// Assertion functions
function assertIsString(value: unknown): asserts value is string {
if (typeof value !== 'string') {
throw new Error('Value must be a string');
}
}
// Exhaustive checks
function assertNever(x: never): never {
throw new Error(`Unexpected value: ${x}`);
}---
Async Patterns
Promises and Async/Await
// Promise creation
function delay(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// Async/await with error handling
async function fetchUser(id: string): Promise<Result<User>> {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
return {
success: false,
error: new Error(`HTTP ${response.status}`),
};
}
const data = await response.json();
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error : new Error(String(error)),
};
}
}
// Parallel execution
async function fetchAllUsers(ids: string[]): Promise<User[]> {
const results = await Promise.all(ids.map((id) => fetchUser(id)));
return results
.filter((r): r is { success: true; data: User } => r.success)
.map((r) => r.data);
}
// Promise.allSettled for partial failures
async function fetchUsersSettled(ids: string[]) {
const results = await Promise.allSettled(
ids.map((id) => fetch(`/api/users/${id}`).then((r) => r.json()))
);
return results.map((result, index) => ({
id: ids[index],
status: result.status,
value: result.status === 'fulfilled' ? result.value : null,
error: result.status === 'rejected' ? result.reason : null,
}));
}
// Sequential execution with reduce
async function processSequentially<T, R>(
items: T[],
processor: (item: T) => Promise<R>
): Promise<R[]> {
return items.reduce(async (accPromise, item) => {
const acc = await accPromise;
const result = await processor(item);
return [...acc, result];
}, Promise.resolve([] as R[]));
}Async Iterators
// Async generator
async function* paginate<T>(
fetcher: (page: number) => Promise<{ data: T[]; hasMore: boolean }>
): AsyncGenerator<T[], void, unknown> {
let page = 1;
let hasMore = true;
while (hasMore) {
const result = await fetcher(page);
yield result.data;
hasMore = result.hasMore;
page++;
}
}
// Using async iterator
async function getAllItems() {
const items: Item[] = [];
for await (const batch of paginate(fetchPage)) {
items.push(...batch);
}
return items;
}
// Async iterator utilities
async function* map<T, R>(
iterable: AsyncIterable<T>,
fn: (item: T) => R | Promise<R>
): AsyncGenerator<R> {
for await (const item of iterable) {
yield await fn(item);
}
}
async function* filter<T>(
iterable: AsyncIterable<T>,
predicate: (item: T) => boolean | Promise<boolean>
): AsyncGenerator<T> {
for await (const item of iterable) {
if (await predicate(item)) {
yield item;
}
}
}
async function* take<T>(
iterable: AsyncIterable<T>,
count: number
): AsyncGenerator<T> {
let taken = 0;
for await (const item of iterable) {
if (taken >= count) break;
yield item;
taken++;
}
}---
Functional Patterns
Higher-Order Functions
// Currying
const add = (a: number) => (b: number) => a + b;
const add5 = add(5);
console.log(add5(3)); // 8
// Pipe and compose
const pipe =
<T>(...fns: Array<(arg: T) => T>) =>
(value: T): T =>
fns.reduce((acc, fn) => fn(acc), value);
const compose =
<T>(...fns: Array<(arg: T) => T>) =>
(value: T): T =>
fns.reduceRight((acc, fn) => fn(acc), value);
// Usage
const processString = pipe(
(s: string) => s.trim(),
(s: string) => s.toLowerCase(),
(s: string) => s.replace(/\s+/g, '-')
);
// Memoization
function memoize<Args extends unknown[], Result>(
fn: (...args: Args) => Result
): (...args: Args) => Result {
const cache = new Map<string, Result>();
return (...args: Args): Result => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key)!;
}
const result = fn(...args);
cache.set(key, result);
return result;
};
}
// Debounce
function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let timeoutId: ReturnType<typeof setTimeout>;
return (...args: Parameters<T>) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
}
// Throttle
function throttle<T extends (...args: any[]) => any>(
fn: T,
limit: number
): (...args: Parameters<T>) => void {
let inThrottle = false;
return (...args: Parameters<T>) => {
if (!inThrottle) {
fn(...args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}Immutable Data Patterns
// Object updates
const updateUser = (user: User, updates: Partial<User>): User => ({
...user,
...updates,
});
// Nested updates
interface State {
users: Record<string, User>;
settings: {
theme: string;
notifications: boolean;
};
}
const updateNestedState = (
state: State,
userId: string,
userUpdate: Partial<User>
): State => ({
...state,
users: {
...state.users,
[userId]: {
...state.users[userId],
...userUpdate,
},
},
});
// Array operations (immutable)
const addItem = <T>(arr: T[], item: T): T[] => [...arr, item];
const removeItem = <T>(arr: T[], index: number): T[] => [
...arr.slice(0, index),
...arr.slice(index + 1),
];
const updateItem = <T>(arr: T[], index: number, item: T): T[] => [
...arr.slice(0, index),
item,
...arr.slice(index + 1),
];---
Modern JavaScript Features
Destructuring and Spread
// Object destructuring with defaults and rename
const { name, email, role = 'user', id: odentifier } = user;
// Nested destructuring
const {
address: { city, country },
} = user;
// Array destructuring
const [first, second, ...rest] = items;
const [, , third] = items; // Skip elements
// Function parameter destructuring
function createUser({
name,
email,
role = 'user',
}: {
name: string;
email: string;
role?: string;
}) {
return { id: generateId(), name, email, role };
}
// Spread for merging
const merged = { ...defaults, ...overrides };
const combined = [...arr1, ...arr2];Optional Chaining and Nullish Coalescing
// Optional chaining
const city = user?.address?.city;
const firstItem = items?.[0];
const result = callback?.();
// Nullish coalescing (only null/undefined)
const value = input ?? defaultValue;
// Combining them
const displayName = user?.profile?.displayName ?? user?.name ?? 'Anonymous';
// Logical assignment operators
let config = { timeout: 0 };
config.timeout ||= 5000; // Assigns if falsy (won't assign, 0 is falsy)
config.timeout ??= 5000; // Assigns if null/undefined (won't assign)
config.retries ??= 3; // Assigns (undefined)---
Error Handling
// Custom error classes
class AppError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number = 500
) {
super(message);
this.name = 'AppError';
Error.captureStackTrace(this, this.constructor);
}
}
class ValidationError extends AppError {
constructor(
message: string,
public fields: Record<string, string[]>
) {
super(message, 'VALIDATION_ERROR', 400);
this.name = 'ValidationError';
}
}
// Result type pattern (no exceptions)
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
function ok<T>(value: T): Result<T, never> {
return { ok: true, value };
}
function err<E>(error: E): Result<never, E> {
return { ok: false, error };
}
// Using Result
function parseJSON<T>(json: string): Result<T, SyntaxError> {
try {
return ok(JSON.parse(json));
} catch (e) {
return err(e as SyntaxError);
}
}
// Chaining Results
function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> {
return result.ok ? ok(fn(result.value)) : result;
}
function flatMap<T, U, E>(
result: Result<T, E>,
fn: (value: T) => Result<U, E>
): Result<U, E> {
return result.ok ? fn(result.value) : result;
}---
Module Patterns
// Named exports
export const API_URL = 'https://api.example.com';
export function fetchData() {}
export class ApiClient {}
// Default export
export default class Logger {}
// Re-exports
export { UserService } from './user-service';
export { default as Logger } from './logger';
export * from './types';
export * as utils from './utils';
// Dynamic imports
async function loadModule() {
const { default: Chart } = await import('./chart');
return new Chart();
}
// Conditional imports
const adapter = await import(
process.env.NODE_ENV === 'test' ? './mock-adapter' : './real-adapter'
);---
Related Skills
- [[frontend]] - React/Next.js development
- [[backend]] - Node.js server development
- [[testing]] - Jest, Vitest testing
{
"_comment": "Package.json Template - Node.js/TypeScript",
"name": "my-project",
"version": "1.0.0",
"description": "Project description",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"files": [
"dist"
],
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"test": "vitest",
"test:coverage": "vitest --coverage",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check .",
"typecheck": "tsc --noEmit",
"prepare": "husky"
},
"dependencies": {},
"devDependencies": {
"@types/node": "^20.10.0",
"typescript": "^5.3.0",
"tsx": "^4.6.0",
"vitest": "^1.0.0",
"@vitest/coverage-v8": "^1.0.0",
"eslint": "^9.0.0",
"typescript-eslint": "^8.0.0",
"@eslint/js": "^9.0.0",
"eslint-config-prettier": "^9.0.0",
"prettier": "^3.1.0",
"husky": "^9.0.0",
"lint-staged": "^15.0.0"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{json,md,yml}": [
"prettier --write"
]
},
"engines": {
"node": ">=20.0.0"
},
"author": "",
"license": "MIT",
"keywords": [],
"repository": {
"type": "git",
"url": ""
}
}
JavaScript/TypeScript Templates
TypeScript configuration and package.json templates.
Files
| Template | Purpose |
|---|---|
tsconfig.json | Node.js/ESM TypeScript config |
tsconfig.react.json | React/Vite TypeScript config |
package.json | Node.js project with modern tooling |
Usage
Node.js Project
cp templates/tsconfig.json ./tsconfig.json
cp templates/package.json ./package.json
# Update package.json name/description
# Install dependencies
npm installReact Project
cp templates/tsconfig.react.json ./tsconfig.json
# For Vite, also create tsconfig.node.json:
# { "extends": "./tsconfig.json", "include": ["vite.config.ts"] }Key Configuration
tsconfig.json (Node.js)
- Target: ES2022 (modern Node.js)
- Module: NodeNext (native ESM)
- Strict: All strict checks enabled
- Path aliases:
@/*→./src/*
tsconfig.react.json
- Target: ES2020 (browser compatibility)
- JSX: react-jsx (React 17+)
- Module: ESNext (bundler mode)
- No emit: Bundler handles output
package.json
Modern tooling stack:
- tsx: Fast TypeScript execution
- vitest: Fast testing
- eslint 9: Flat config
- prettier: Formatting
- husky + lint-staged: Pre-commit hooks
Scripts
npm run dev # Development with watch
npm run build # Production build
npm test # Run tests
npm run lint # Lint code
npm run format # Format code
npm run typecheck # Type check onlyPath Aliases
Configure in both tsconfig.json and bundler:
// tsconfig.json
{
"paths": {
"@/*": ["./src/*"]
}
}// vite.config.ts
export default defineConfig({
resolve: {
alias: {
'@': resolve(__dirname, './src'),
},
},
});ESM vs CommonJS
This template uses ESM ("type": "module"). For CommonJS:
{
"type": "commonjs",
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "Node"
}
}{
"$schema": "https://json.schemastore.org/tsconfig",
"_comment": "TypeScript Configuration Template - Node.js/ESM",
"compilerOptions": {
// ===========================================
// Language & Environment
// ===========================================
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
// ===========================================
// Output
// ===========================================
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
// ===========================================
// Strict Type Checking
// ===========================================
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"useUnknownInCatchVariables": true,
"alwaysStrict": true,
// ===========================================
// Additional Checks
// ===========================================
"noUnusedLocals": true,
"noUnusedParameters": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
// ===========================================
// Module Resolution
// ===========================================
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"isolatedModules": true,
// ===========================================
// Path Aliases
// ===========================================
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
// ===========================================
// Emit
// ===========================================
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"removeComments": false,
"incremental": true,
"tsBuildInfoFile": "./.tsbuildinfo"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
}
{
"$schema": "https://json.schemastore.org/tsconfig",
"_comment": "TypeScript Configuration Template - React/Vite",
"compilerOptions": {
// ===========================================
// Language & Environment
// ===========================================
"target": "ES2020",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
// ===========================================
// Bundler Mode (Vite/esbuild)
// ===========================================
"allowImportingTsExtensions": true,
"noEmit": true,
// ===========================================
// Strict Type Checking
// ===========================================
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
// ===========================================
// Module Resolution
// ===========================================
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"isolatedModules": true,
// ===========================================
// Path Aliases
// ===========================================
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"],
"@hooks/*": ["./src/hooks/*"],
"@utils/*": ["./src/utils/*"]
},
// ===========================================
// Other
// ===========================================
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"useDefineForClassFields": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
Related skills
AI & Agent Buildingagents