TypeScript Developer Guidelines
Derived from the Google TypeScript Style Guide, which is the baseline for every rule here. Where Google's stated rationale has since expired - usually because it rested on ES5 downlevel emit, which no longer exists - this skill takes the current position instead and says so. Every such departure is listed in google-style-deltas.md; nothing is changed silently.
Always determine the TypeScript version and the tsconfig before giving guidance. 6.0 changed the defaults (
strict,module,types) and removed the ES5 target; 7.0 removed more and ships without a programmatic API. What compiles on one line will not on another. Read typescript-versions.md.strictis the floor, not the target.strict: truealone leavesnoUncheckedIndexedAccess,exactOptionalPropertyTypesandverbatimModuleSyntaxoff, and each of those catches a class of bug the strict family does not. Read tsconfig.md.Never widen a type to make an error go away. No
any, noasto silence a mismatch, no!to dismiss a null, no@ts-ignore. Each converts a compile error into a runtime one. Narrow, guard, or fix the type. Read any-and-unknown.md.Never generate an
enum. Notconst enum, not a string enum, not a numeric one. Use a literal union, or anas constobject when the values are needed at runtime. Enums are the one TypeScript type construct that emits JavaScript, which makes them non-erasable, and numeric enums are not even type-safe. enums-and-constants.md carries the replacement for every enum shape. If the codebase already uses enums, match it and raise it rather than silently mixing.Prefer the construct that emits nothing. The same erasability rule bans
namespaceand makes parameter properties conditional - Node's type stripper anderasableSyntaxOnlyboth reject anything that is not a pure annotation.Match the surrounding code and raise the conflict. These rules apply to new code. In a codebase that consistently does otherwise, follow the local convention and say so rather than silently mixing styles.
After generating code, type-check it and run the tests.
tsc --noEmitplus the project's test command. Do not skip this - inference, generic constraints and exhaustiveness all fail in ways that are not obvious by reading.
Every reference carries a ## Version notes section stating what differs across TypeScript 5.x, 6.0 and 7.0, and a ## Gotchas list of the specific mistakes agents make in that area. Read the gotchas even when skimming.
Determining the Version and Configuration
Step 1. Read typescript in package.json devDependencies, not a global install. Confirm with npx tsc --version.
Step 2. Read the whole tsconfig.json, following extends. The strictness flags decide what advice is even applicable - noUncheckedIndexedAccess changes what every array access returns.
Step 3. Check for erasableSyntaxOnly, and whether the project runs .ts directly under Node. Either one bans enums, namespaces and parameter properties.
Step 4. Check the module format - module, type in package.json, and whether imports carry .js extensions. This decides import style before anything else.
Step 5. New projects: TypeScript 6.0. Read typescript-versions.md for why 7.0 is not yet the default recommendation.
Foundations
- TypeScript Versions: The 6.0 baseline, what 6.0 removed and redefaulted, the 7.0 Go-native compiler and its missing programmatic API, running 6 and 7 side by side, and the 5.x → 6 → 7 path. Read typescript-versions.md
- tsconfig: The recommended configuration flag by flag - the strict family and what it misses,
noUncheckedIndexedAccess,exactOptionalPropertyTypes,verbatimModuleSyntax,isolatedModules,isolatedDeclarations,erasableSyntaxOnly. Read tsconfig.md - Enforcement: Which rules a linter can enforce and which only review catches, the typescript-eslint mapping, formatter setup, and what breaks on TypeScript 7. Read enforcement.md
- Google Style Deltas: Every point where this skill departs from the Google guide, with the expired rationale that justifies each. Read google-style-deltas.md
Source Files
- File Structure: Encoding, the required order of copyright,
@fileoverview, imports and implementation, escape sequences, and non-ASCII characters. Read file-structure.md - Imports and Exports: The four import forms and when each applies, named versus namespace imports, why default exports are banned, mutable exports, container classes,
import type, ES modules,.jsextensions and packageexports. Read imports-and-exports.md
Language
- Variables and Literals:
constoverletover nevervar, one declaration per statement, array and object literals, spread, destructuring, string quoting, template literals, number literals, and type coercion. Read variables-and-literals.md - Functions: Declarations versus expressions versus arrows,
thisand why rebinding is banned, callbacks, arrow properties, event handlers, parameter defaults, rest and spread, and overloads. Read functions.md - Classes:
#privateoverprivate,readonly, field initializers, why parameter properties are now conditional, visibility, accessors, static members, and the prototype rules. Read classes.md - Control Flow: Braces, assignment in conditions, iterating arrays and objects,
switchand exhaustiveness,===, and grouping parentheses. Read control-flow.md - Errors and Exceptions: Only throw
Error,unknownincatch, custom error classes andcause, empty catch blocks, keepingtryfocused, and when aResulttype beats throwing. Read errors-and-exceptions.md
Type System
- Type Inference and satisfies: What to annotate and what to leave inferred, return types, annotating structural implementations at the declaration, and
satisfiesas the first choice before any assertion. Read type-inference.md - Nullability:
undefinedversusnull, why nullability never belongs in a type alias, optional properties versus| undefined,exactOptionalPropertyTypes, and narrowing. Read nullability.md - Interfaces and Type Aliases: Interfaces for object shapes, aliases for unions and computed types, declaration merging, and what Google's rule actually says. Read interfaces-and-type-aliases.md
- Arrays and Collections:
T[]versusArray<T>,readonly, index signatures,MapandSetandRecord, and whatnoUncheckedIndexedAccesschanges. Read arrays-and-collections.md - any and unknown: Why
anyis banned,unknownand narrowing,{}versusobjectversusunknown, and the discipline for the rare suppression. Read any-and-unknown.md - Generics: Constraints, why return-type-only generics are banned,
consttype parameters,NoInfer, variance annotations, and when not to reach for a generic. Read generics.md - Advanced Types: Mapped and conditional types and Google's restraint rule, template literal types, discriminated unions, branded types for nominal typing, type predicates and assertion functions. Read advanced-types.md
Modern Syntax
- Enums and Constants: Why
as constobjects and literal unions replaceenum, theconst enumban, and the erasability rule behind both. Read enums-and-constants.md - Decorators: Standard stage-3 decorators versus
experimentalDecorators, why the two cannot be mixed, the framework-only rule, and theaccessorkeyword. Read decorators.md
Async
- Async and Promises: Floating promises,
async/awaitover.then, concurrency withPromise.allandallSettled, cancellation withAbortSignal, and async error handling. Read async-and-promises.md - Resource Management:
usingandawait using,Symbol.disposeandSymbol.asyncDispose,DisposableStack, and where they replacetry/finally. Read resource-management.md
Conventions
- Naming: The casing table, descriptive names, acronyms as words, type parameters, test names, the underscore ban, what counts as a constant, and aliases. Read naming.md
- Comments and JSDoc: JSDoc versus line comments, form and markdown, which tags are banned because TypeScript already says it, and documenting parameters and returns. Read comments-and-jsdoc.md
- Disallowed Features: Wrapper objects, semicolons and ASI,
debugger,with,eval, non-standard syntax, namespaces, and modifying builtins. Read disallowed-features.md
Testing
- Testing: Structure and naming, what to assert, type-level testing, why
anyin a test is still a bug, and test doubles. Read testing.md
Checklist
- Best Practices Checklist: Every rule in one scannable list, plus the ones that cause the most damage. Use this for a review pass over existing code. Read checklist.md