TypeScript Strict Mode Best Practices
Quick Start
typescript
// Enable strict in tsconfig.json
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true
}
}
Core Principles
- •Strict null checks: Handle
undefinedandnullexplicitly - •No implicit any: Always declare types, avoid
any - •Readonly by default: Use
readonlyfor immutable data - •Discriminated unions: Use type guards with tagged unions
Type Definition Patterns
AST Node Types
typescript
// Discriminated union for AST nodes
type Expr =
| { type: "NumberLiteral"; value: number }
| { type: "BinaryExpr"; op: string; left: Expr; right: Expr }
| { type: "Identifier"; name: string };
// Type guard
function isNumberLiteral(expr: Expr): expr is Extract<Expr, { type: "NumberLiteral" }> {
return expr.type === "NumberLiteral";
}
Generic Types
typescript
// Constrained generics
function map<T, U>(arr: readonly T[], fn: (item: T, index: number) => U): U[] {
return arr.map(fn);
}
// Conditional types
type Unwrap<T> = T extends Promise<infer U> ? U : T;
Declaration Files
typescript
// module.d.ts
declare module "lea-lang" {
export function run(code: string): unknown;
export function parse(code: string): Program;
}
Common Patterns
- •Use
unknownoveranyfor safer type narrowing - •Prefer
interfacefor extendable types,typefor unions - •Use
as constfor literal types - •Leverage
satisfiesfor type checking without widening
Reference Files
- •references/generics.md - Advanced generic patterns
- •references/type-guards.md - Type narrowing techniques