typescript-engineering

TypeScript Engineering

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "typescript-engineering" with this command: npx skills add gonzaloserrano/dotfiles/gonzaloserrano-dotfiles-typescript-engineering

TypeScript Engineering

Comprehensive guidelines for writing production-quality TypeScript based on Google's TypeScript Style Guide.

Naming Conventions

Type Convention Example

Classes, Interfaces, Types, Enums UpperCamelCase

UserService , HttpClient

Variables, Parameters, Functions lowerCamelCase

userName , processData

Global Constants, Enum Values CONSTANT_CASE

MAX_RETRIES , Status.ACTIVE

Type Parameters Single letter or UpperCamelCase

T , ResponseType

Naming Principles

  • Descriptive names, avoid ambiguous abbreviations

  • Treat acronyms as words: loadHttpUrl not loadHTTPURL

  • No prefixes like opt_ for optional parameters

  • No trailing underscores for private properties

  • Single-letter variables only when scope is <10 lines

Variable Declarations

// Always use const by default const users = getUsers();

// Use let only when reassignment is needed let count = 0; count++;

// Never use var // var x = 1; // WRONG

// One variable per declaration const a = 1; const b = 2; // const a = 1, b = 2; // WRONG

Types and Interfaces

Prefer Interfaces Over Type Aliases

// Good: interface for object shapes interface User { id: string; name: string; email?: string; }

// Avoid: type alias for object shapes type User = { id: string; name: string; };

// Type aliases OK for unions, intersections, mapped types type Status = 'active' | 'inactive'; type Combined = TypeA & TypeB;

Type Inference

Leverage inference for trivially inferred types:

// Good: inference is clear const name = 'Alice'; const items = [1, 2, 3];

// Good: explicit for complex expressions const result: ProcessedData = complexTransformation(input);

Array Types

// Simple types: use T[] const numbers: number[]; const names: readonly string[];

// Multi-dimensional: use T[][] const matrix: number[][];

// Complex types: use Array<T> const handlers: Array<(event: Event) => void>;

Null and Undefined

// Prefer optional fields over union with undefined interface Config { timeout?: number; // Good // timeout: number | undefined; // Avoid }

// Type aliases must NOT include |null or |undefined type UserId = string; // Good // type UserId = string | null; // WRONG

// May use == for null comparison (catches both null and undefined) if (value == null) { // handles both null and undefined }

Types to Avoid

// Avoid any - use unknown instead function parse(input: unknown): Data { }

// Avoid {} - use unknown, Record<string, T>, or object function process(obj: Record<string, unknown>): void { }

// Use lowercase primitives let name: string; // Good // let name: String; // WRONG

// Never use wrapper objects // new String('hello') // WRONG

Classes

Structure

class UserService { // Fields first, initialized where declared private readonly cache = new Map<string, User>(); private lastAccess: Date | null = null;

// Constructor with parameter properties constructor( private readonly api: ApiClient, private readonly logger: Logger, ) {}

// Methods separated by blank lines async getUser(id: string): Promise<User> { // ... }

private validateId(id: string): boolean { // ... } }

Visibility

class Example { // private by default, only use public when needed externally private internalState = 0;

// readonly for properties never reassigned after construction readonly id: string;

// Never use #private syntax - use TypeScript visibility // #field = 1; // WRONG private field = 1; // Good }

Avoid Arrow Functions as Properties

class Handler { // Avoid: arrow function as property // handleClick = () => { ... };

// Good: instance method handleClick(): void { // ... } }

// Bind at call site if needed element.addEventListener('click', () => handler.handleClick());

Static Methods

  • Never use this in static methods

  • Call on defining class, not subclasses

Functions

Prefer Function Declarations

// Good: function declaration for named functions function processData(input: Data): Result { return transform(input); }

// Arrow functions when type annotation needed const handler: EventHandler = (event) => { // ... };

Arrow Function Bodies

// Concise body only when return value is used const double = (x: number) => x * 2;

// Block body when return should be void const log = (msg: string) => { console.log(msg); };

Parameters

// Use rest parameters, not arguments function sum(...numbers: number[]): number { return numbers.reduce((a, b) => a + b, 0); }

// Destructuring for multiple optional params interface Options { timeout?: number; retries?: number; } function fetch(url: string, { timeout = 5000, retries = 3 }: Options = {}) { // ... }

// Never name a parameter 'arguments'

Imports and Exports

Always Use Named Exports

// Good: named exports export function processData() { } export class UserService { } export interface Config { }

// Never use default exports // export default class UserService { } // WRONG

Import Styles

// Module import for large APIs import * as fs from 'fs';

// Named imports for frequently used symbols import { readFile, writeFile } from 'fs/promises';

// Type-only imports when only used as types import type { User, Config } from './types';

Module Organization

  • Use modules, never namespace Foo { }

  • Never use require()

  • use ES6 imports

  • Use relative imports within same project

  • Avoid excessive ../../../

Control Structures

Always Use Braces

// Good if (condition) { doSomething(); }

// Exception: single-line if if (condition) return early;

Loops

// Prefer for...of for arrays for (const item of items) { process(item); }

// Use Object methods with for...of for objects for (const [key, value] of Object.entries(obj)) { // ... }

// Never use unfiltered for...in on arrays

Equality

// Always use === and !== if (a === b) { }

// Exception: == null catches both null and undefined if (value == null) { }

Switch Statements

switch (status) { case Status.Active: handleActive(); break; case Status.Inactive: handleInactive(); break; default: // Always include default, even if empty break; }

Exception Handling

// Always throw Error instances throw new Error('Something went wrong'); // throw 'error'; // WRONG

// Catch with unknown type try { riskyOperation(); } catch (e: unknown) { if (e instanceof Error) { logger.error(e.message); } throw e; }

// Empty catch needs justification comment try { optional(); } catch { // Intentionally ignored: fallback behavior handles this }

Type Assertions

// Use 'as' syntax, not angle brackets const input = value as string; // const input = <string>value; // WRONG in TSX, avoid everywhere

// Double assertion through unknown when needed const config = (rawData as unknown) as Config;

// Add comment explaining why assertion is safe const element = document.getElementById('app') as HTMLElement; // Safe: element exists in index.html

Strings

// Use single quotes for string literals const name = 'Alice';

// Template literals for interpolation or multiline const message = Hello, ${name}!; const query = SELECT * FROM users WHERE id = ?;

// Never use backslash line continuations

Disallowed Features

Feature Alternative

var

const or let

Array() constructor [] literal

Object() constructor {} literal

any type unknown

namespace

modules

require()

import

Default exports Named exports

#private fields private modifier

eval()

Never use

const enum

Regular enum

debugger

Remove before commit

with

Never use

Prototype modification Never modify

Quick Reference

// File structure order: // 1. Copyright (if present) // 2. @fileoverview JSDoc (if present) // 3. Imports // 4. Implementation

// Prefer interfaces for object types interface User { }

// Named exports only export function process() { } export class Service { }

// const by default, let when needed const x = 1; let y = 2;

// Strict equality if (a === b) { }

// Unknown over any function parse(data: unknown) { }

// Throw Error instances throw new Error('message');

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

python-engineering

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

go-code-review

No summary provided by upstream source.

Repository SourceNeeds Review
General

shell-engineering

No summary provided by upstream source.

Repository SourceNeeds Review