TypeScript Local Development

Purpose

Reference for TypeScript tooling: compiler configuration, IDE integration, escaping the type checker when necessary, and typing third-party JavaScript.

Implementation Notes

tsconfig.json — Key Options

{
  "compilerOptions": {
    "lib":                  ["esnext", "dom", "dom.iterable"],
    "target":               "esnext",
    "strict":               true,
    "skipLibCheck":         true,
    "verbatimModuleSyntax": true,
    "esModuleInterop":      true,
    "moduleDetection":      "force",
    "noUncheckedIndexedAccess": true,
    "outDir":               "./dist",
    "rootDir":              "./src"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
OptionEffect
libWhich runtime APIs are available. Add "dom" for browser globals.
targetECMAScript version of the emitted JavaScript. Pin to a specific version (e.g. "es2024") before shipping.
strictEnables all strict checks (strictNullChecks, noImplicitAny, etc.). Always on for new projects.
skipLibCheckSkips type-checking of .d.ts files in node_modules — dramatically speeds up compilation.
verbatimModuleSyntaxForces import type for type-only imports; simplifies module boundary handling.
esModuleInteropAllows import x from 'commonjs-module' syntax when interoperating with CommonJS.
moduleDetectionSet to "force" to treat every file as a module. Correct for any new project.
noUncheckedIndexedAccessIndex access (arr[i], obj[key]) returns T | undefined — prevents off-by-one runtime crashes.
outDir / rootDirOutput directory and source root for compiled JS.
include / excludeGlob patterns controlling which files are compiled.

TypeScript Language Server and IDE Integration

The TypeScript Language Server (tsserver) powers editor features in VS Code and most other editors that support the Language Server Protocol:

  • Type inference and hover documentation
  • Inline error highlighting
  • Autocompletion and signature help
  • Refactoring (rename, extract, organise imports)

The language server reads tsconfig.json automatically from your project root. No additional configuration is needed for VS Code — it ships with a bundled TypeScript version, which you can override per-workspace to match the project’s installed version.

@ts-ignore / // @ts-nocheck — Use Very Sparingly

Suppress errors on the next line:

// @ts-ignore
const x: number = "not a number"; // error suppressed

Disable type checking for an entire file:

// @ts-nocheck
 
const x: number = "not a number";    // no error

Both are escape hatches that defeat the type system. Use only:

  • When integrating a genuinely untyped third-party script with no available types.
  • During a large JS → TS migration where a specific file cannot be addressed yet.

Prefer @ts-ignore (single line) over @ts-nocheck (whole file). Add a comment explaining why the suppression is necessary.

Declaration Files (.d.ts) for Typing JS Libraries

.d.ts files contain type information only — no runtime code. TypeScript uses them to provide type hints for JavaScript that exists outside the compiler’s control.

Global augmentation example — typing a JS library loaded via <script> tag:

// globals.d.ts
declare global {
  interface Window {
    google: GoogleAPI;
  }
}
 
interface GoogleAPI {
  accounts: {
    id: {
      initialize: (config: { client_id: string; callback: (r: any) => void }) => void;
      renderButton: (el: HTMLElement, opts: { theme?: string; size?: string }) => void;
      prompt: () => void;
    };
  };
}
 
export {}; // ensure this is treated as a module

Module declaration — typing an untyped npm package:

// pregnantgoku.d.ts
declare module "pregnantgoku" {
  export function kamahameha(target: [number, number]): void;
  export type Saiyan = { name: string; powerLevel: number };
}

@types/ Packages — Community Type Definitions

DefinitelyTyped publishes community-maintained type declarations for popular JS libraries as @types/<package>:

npm install --save-dev @types/lodash
npm install --save-dev @types/node

TypeScript resolves these automatically. Check DefinitelyTyped before writing your own declarations.

Priority for untyped libraries:

  1. Check for @types/<lib> on npm.
  2. If unavailable, write a .d.ts module declaration.
  3. As a last resort, add "allowJs": true to tsconfig.json and let TypeScript infer types from JS source.

Vanilla Vite + TypeScript Setup

Vite is the recommended build tool for new TypeScript projects — fast (esbuild for development, Rollup for production), simple config, and built-in HMR:

npm create vite@latest my-app -- --template vanilla-ts
cd my-app
npm install
npm run dev

Vite scaffolds a minimal tsconfig.json and a vite.config.ts. Key points:

  • Vite transpiles TypeScript (strips types) but does not type-check during dev — run tsc --noEmit separately for type checking.
  • Use the vite-plugin-checker plugin or a pre-commit hook with tsc for CI type checking.

Trade-offs

  • Enable strict on all new projects. Disabling it during a JS → TS migration is acceptable, but re-enable flag by flag as the codebase matures.
  • skipLibCheck: true trades correctness for speed — usually the right call; downstream declaration errors are rarely actionable.
  • Handwritten .d.ts files are brittle — they diverge from the actual library as it updates. Prefer @types/ packages where available.

References