registry/skills/typescript-development/SKILL.md
This skill should be used when the user asks to "write TypeScript code", "create a TypeScript module", "define TypeScript types", "add type annotations", "use generics", "handle errors in TypeScript", "set up tsconfig", "organize TypeScript project", or when writing any TypeScript code that is not tied to a specific library or framework. Covers type system, strict mode, naming conventions, error handling, async patterns, and project structure.
npx skillsauth add provectus/awos-recruitment typescript-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill covers modern TypeScript best practices for writing clean, type-safe code. It focuses on the language itself — no library or framework specifics. Apply these conventions to all TypeScript code in the project.
Always enable strict: true in tsconfig.json. Never disable individual strict flags. This is non-negotiable — it catches entire categories of bugs at compile time.
Key strict behaviors:
null and undefined are distinct types (no implicit null)any)unknown, not any| Construct | Convention | Example |
|---|---|---|
| Variables, functions | camelCase | getUserName, isActive |
| Classes | PascalCase | UserService, HttpClient |
| Interfaces | PascalCase (no I prefix) | User, not IUser |
| Type aliases | PascalCase | ApiResponse, EventMap |
| Constants | camelCase or UPPER_SNAKE | maxRetries or MAX_RETRIES |
| Enum-like objects | PascalCase key, camelCase/string values | Status.Active |
| Generic parameters | Single uppercase or descriptive | T, TResult, K extends keyof T |
| File names | kebab-case | user-service.ts, api-client.ts |
| Boolean variables | Prefix with is, has, can, should | isValid, hasPermission |
// Parameters and return: always annotate
function calculateTotal(items: LineItem[], taxRate: number): number {
return items.reduce((sum, item) => sum + item.price, 0) * (1 + taxRate);
}
// Variable: skip annotation when inferred
const total = calculateTotal(items, 0.1); // inferred as number
// Variable: annotate when not obvious
const cache: Map<string, User> = new Map();
// Prefer interface for object shapes
interface User {
id: string;
name: string;
email: string;
}
// Use type alias for unions, intersections, mapped types
type Result<T> = { ok: true; value: T } | { ok: false; error: Error };
type StringKeys<T> = Extract<keyof T, string>;
anyUse unknown instead of any for values of uncertain type. Narrow with type guards before use:
// Bad
function parse(input: any): string { return input.name; }
// Good
function parse(input: unknown): string {
if (typeof input === "object" && input !== null && "name" in input) {
return String((input as { name: unknown }).name);
}
throw new Error("Invalid input");
}
Acceptable uses of any: Only when interfacing with untyped external code and a proper type cannot be defined. Always add a comment explaining why.
Model state variants with a shared literal discriminant:
type LoadingState<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; error: Error };
Always include an exhaustive check using never:
function assertNever(value: never): never {
throw new Error(`Unexpected value: ${value}`);
}
function render<T>(state: LoadingState<T>): string {
switch (state.status) {
case "idle": return "Ready";
case "loading": return "Loading...";
case "success": return String(state.data);
case "error": return state.error.message;
default: return assertNever(state);
}
}
try {
await riskyOperation();
} catch (error: unknown) {
if (error instanceof AppError) {
handleAppError(error);
} else if (error instanceof Error) {
handleGenericError(error);
} else {
handleUnknown(String(error));
}
}
class AppError extends Error {
constructor(
message: string,
readonly code: string,
readonly statusCode: number = 500,
) {
super(message);
this.name = "AppError";
}
}
For expected failure paths, prefer a typed Result over throwing:
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
Prefer as const objects over TypeScript enum:
const Status = {
Active: "active",
Inactive: "inactive",
Pending: "pending",
} as const;
type Status = (typeof Status)[keyof typeof Status];
Why: No runtime code emitted, better tree-shaking, interoperates with plain strings.
Promise<T> return types on async functionsPromise.all for independent concurrent operationsPromise.allSettled when partial failure is acceptablevoid for async function returns — use Promise<void>async function fetchUserData(id: string): Promise<UserData> {
const [profile, orders] = await Promise.all([
fetchProfile(id),
fetchOrders(id),
]);
return { profile, orders };
}
readonly on properties that should not change after initializationreadonly T[] (or ReadonlyArray<T>) for array parameters that should not be mutatedas const for literal objects and arrays that should be fully immutable{ ...obj, key: newValue } over obj.key = newValueUse import type for imports used only as types:
import type { User } from "./models.js";
import { createUser } from "./models.js";
This prevents circular dependency issues and ensures types are erased at compile time.
When using "type": "module" in package.json with "module": "Node16", all relative imports must include the .js extension — even in .ts source files:
import { helper } from "./utils.js"; // Correct
import { helper } from "./utils"; // Wrong — fails at runtime
| Mistake | Fix |
|---|---|
| Using any | Use unknown and narrow with type guards |
| Missing return type on exports | Add explicit return type annotation |
| enum for string constants | Use as const object + derived union type |
| Mutable function parameters | Mark arrays/objects as readonly |
| Bare catch (error) | Use catch (error: unknown) and narrow |
| Missing .js in ESM imports | Add .js extension to all relative imports |
| strict: false in tsconfig | Always use strict: true |
| I prefix on interfaces | Drop the prefix: User, not IUser |
| Optional props for distinct states | Use discriminated unions |
| Type assertions (as T) | Prefer type guards and narrowing |
For detailed type system features and advanced patterns, consult:
references/type-system.md — Generics, utility types, conditional types, mapped types, template literal types, type guards, discriminated unions, branded types, satisfies operator, const assertions, declaration mergingreferences/patterns.md — Immutability patterns, error handling (Result type, custom errors), async patterns (generators, concurrency), builder pattern, type-safe event emitter, overloaded functions, module patterns, enum alternatives, assertion functions, narrowing patternsreferences/type-inference.md — Variable inference, function return inference, generic inference, contextual typing, satisfies operator, infer keyword, control flow analysis, type guards, narrowing patterns, best practices for when to annotate vs let inference workreferences/project-structure.md — tsconfig.json essentials (strict mode flags, module config, safety flags), ESM/CJS setup, directory layout, organizing types, barrel exports, declaration files, import organization, path aliases, gitignoredevelopment
Insurance underwriting domain knowledge for building automated submission processing systems. Covers submission-to-bind lifecycle, document extraction patterns, compliance gates (sanctions, licensing, clearance), human-in-the-loop design for regulated financial services, confidence calibration for extracted fields, operating mode progression (manual to automated), and evidence traceability requirements. Use when designing or implementing underwriting pipelines, extraction agents, compliance workflows, HITL review systems, or decision package assembly for insurance or MGA operations.
development
Use when working with Terraform or OpenTofu - creating modules, writing tests (native test framework, Terratest), setting up CI/CD pipelines, reviewing configurations, choosing between testing approaches, debugging state issues, implementing security scanning (trivy, checkov), or making infrastructure-as-code architecture decisions. Enforces Provectus opinionated conventions (exact version pinning, etc.) on top of community best practices.
development
This skill should be used when the user asks to "write Swift code", "create a Swift type", "set up a Swift package", "review Swift code", "refactor Swift", "use async/await in Swift", "fix Swift style", or when generating any Swift source code regardless of target platform. Provides modern Swift 6+ best practices covering type system, optionals, concurrency, error handling, protocols, generics, and idiomatic patterns. Does not cover any specific platform or framework.
development
This skill should be used when the user asks to "create a page", "add an entity", "build a widget", "create a feature", "scaffold FSD structure", "refactor to FSD", "where should I put this code", "what layer does X go in", "organize my React code", "FSD compliant", "fix layer violation", "explain FSD", "why is this in this layer", "review my FSD structure", or when writing, reviewing, or refactoring React/TypeScript code to ensure Feature-Sliced Design architecture compliance. Also triggers when the user places code in the wrong layer, imports across layers incorrectly, or breaks FSD conventions — the agent should proactively explain the violation and teach the correct approach.