TypeScript Standard

The TypeScript standard is the greenfield default for Wavenumber browser, frontend, and JavaScript-facing library projects. It uses TypeScript as a defect-prevention layer at module, function, event, runtime-data, and package boundaries.

Profiles

typescript-web-app
Browser application or browser-facing library built from owned TypeScript, CSS, tests, docs, contracts, package scripts, and strict typecheck signoff.
python-ts-app
Python package or service that serves a TypeScript browser runtime. It inherits the TypeScript web rules and adds uv, Hatchling, Ruff, Pyright, and Python-to-browser API contract expectations.

default_typescript_web_standard

Returns the greenfield browser TypeScript and CSS profile.

default_python_ts_standard

Returns the Python-served TypeScript browser application profile.

render_typescript_web_standard

Renders the greenfield TypeScript browser profile for human or machine use.

render_python_ts_standard

Renders the Python-served TypeScript app profile for human or machine use.

Greenfield Rule

New owned browser and JavaScript-facing source starts as .ts or .tsx. Checked JavaScript remains a compatibility and migration path under the JavaScript profiles, but it is not the target state for new reusable browser runtimes, app code, or libraries.

Local variables may rely on inference when the initializer is obvious. Public and exported functions, callbacks, event handlers, async results, config objects, service payloads, package exports, and browser message or storage contracts need TypeScript-visible parameter and return shapes.

External data starts as unknown and must be narrowed by a guard, parser, schema, or equivalent boundary validator before it reaches domain logic. State, action, mode, event, and protocol shapes should use discriminated unions, literal unions, readonly, as const, and satisfies where those constructs preserve intent.

Required Files

Required Commands

package.json must declare build, typecheck, lint, test, and signoff scripts. Package-manager installation and update verbs come from the selected package manager, not npm lifecycle scripts. The signoff script should invoke typecheck, lint, and test so a single command proves the TypeScript guardrails are active. Rack signoff may wrap the same package scripts when a project wants one cross-language signoff entry point.

Compiler Guardrails

The typecheck lane must use noEmit: true. Build output may be emitted by a separate compiler or bundler configuration, but the signoff typecheck command must be able to fail without writing generated files.

The effective typecheck config must enable these guardrails:

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "noPropertyAccessFromIndexSignature": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "useUnknownInCatchVariables": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,
    "noEmit": true
  }
}

Projects must not disable strict sub-options such as noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, or alwaysStrict.

allowJs: true is migration-only. skipLibCheck: true is exception-only. Both settings need explicit TypeScript metadata in the dev-std config before the audit will pass.

Runtime Posture

target, module, and moduleResolution are profile posture, not universal guardrails. Browser applications commonly use target: "ES2022", module: "ESNext", and moduleResolution: "bundler". Node-targeting libraries commonly need module: "NodeNext" and moduleResolution: "NodeNext". The audit enforces guardrails and command shape; project build scripts own runtime-specific emit details.

Browser runtime and library code should use erasableSyntaxOnly: true when the project wants source that stays close to JavaScript semantics. Projects that need enums, namespaces, decorator metadata, or another transform-only construct should document the build dependency and review trigger.

TypeScript Config Inheritance

The audit accepts JSONC syntax for TypeScript config files, including $schema URL strings, line comments, block comments, and trailing commas. Comment and trailing-comma stripping is string-aware so URL values and path strings are preserved before JSON parsing.

The audit resolves local-file extends chains in tsconfig.json or the configured typecheck config and merges inherited compilerOptions before checking guardrails. Resolved config files must stay inside the project root and circular inheritance is invalid.

Package-based extends values are unauditable without installing dependencies. They may pass only when the project declares an explicit exception:

[typescript.exceptions]
package_extends = "docs/design/typescript-config-exception.html"

The referenced document or plan must explain the inherited package config, why local-file inheritance is not used, and when the exception must be reviewed.

Migration Lane

Existing checked-JavaScript projects may port gradually. The greenfield TypeScript profiles allow temporary owned JavaScript and allowJs: true only when migration metadata is present:

[typescript.migration]
allow_js = true
tracking_ref = "docs/plans/typescript-port/plan.md"
remove_when = "All owned src JavaScript has been converted to TypeScript."

The tracking ref may be a local plan, local design note, or external issue. The removal condition must be concrete enough for signoff reviewers to know when the exception should disappear. Port reusable module boundaries first, then shared state and event contracts, then leaf DOM wiring.

Exception Metadata

TypeScript exceptions use [typescript.exceptions]. The initial supported keys are package_extends for package-based tsconfig inheritance and skip_lib_check for skipLibCheck: true. Values are local documentation paths, plan refs, or external issue refs that explain scope, rationale, and review trigger.

[typescript.exceptions]
skip_lib_check = "docs/design/third-party-types.html"
package_extends = "wavenumber-eng/example#42"

Source Boundaries

Review Follow-Ups

External review accepted the first TypeScript slice after the JSONC parser and npm lifecycle-script blockers were fixed. Future revisions should decide whether src/lib/ remains reserved for vendored or generated material, whether .mts and .cts count as owned TypeScript implementation suffixes, and whether JSON parse-failure details should always be repo-relative.

Signoff

TypeScript signoff includes dev-std audit, TypeScript compiler checking, TypeScript-aware linting for explicit public boundary types, deterministic tests for non-DOM logic, browser smoke tests where feasible, CSS token hygiene for app projects, and Python API contract tests for Python-served browser apps.

The TypeScript docs follow the current TypeScript config model: config files inherit through extends, Node and bundler resolution are distinct runtime postures, and stricter indexed-access and optional-property checks are part of the modern TypeScript initialization guidance.