ZenoZENO

TypeScript

Shared TypeScript configurations with @zeno-lib/typescript

Zeno uses the @zeno-lib/typescript package to share strict TypeScript configurations across all packages and apps.

You don't have to set tsconfig.json options such as moduleResolution, jsx, lib, strict, Next.js include globs or the Next.js plugin by hand. Extend one config and it sets them for you.

Available configs

The configs form an inheritance chain. Each level extends the previous one:

ConfigExtendsPurpose
base.jsonNoneCore settings (module resolution, ESNext, bundler mode, JSON imports)
strict.jsonbaseEnables strict: true
strictest.jsonstrictExtra strict checks (no unused locals or parameters, no switch fallthrough, no unchecked indexed access)
react.jsonstrictestAdds JSX support and DOM lib
nextjs.jsonreactAdds Next.js plugin, next-env.d.ts, and .next/types includes

Usage

Extend the appropriate config in your package's tsconfig.json:

tsconfig.json
{
  "extends": "@zeno-lib/typescript/nextjs.json"
}

You don't need to set compilerOptions, include or exclude. The config handles module resolution, strict checks, JSX, the DOM libs and the Next.js includes.

Which config to use

Package typeConfig
Next.js app@zeno-lib/typescript/nextjs.json
React library@zeno-lib/typescript/react.json
Non-React package@zeno-lib/typescript/strictest.json
Loose / legacy@zeno-lib/typescript/strict.json

Examples in the repo

PackageConfig
apps/docs@zeno-lib/typescript/nextjs.json
packages/ui@zeno-lib/typescript/react.json
packages/supabase@zeno-lib/typescript/strictest.json
packages/e2e@zeno-lib/typescript/strictest.json

What's included

Base config

Every config inherits these settings:

  • Bundler module resolution: resolves imports the way bundlers such as Vite, Turbopack and webpack do
  • ESNext modules with verbatimModuleSyntax: TypeScript drops imports marked type and leaves every other import and export as written
  • JSON imports: resolveJsonModule is on
  • Incremental builds: TypeScript reuses the previous run's results, so rechecks are faster
  • Isolated modules: every file must compile on its own, as SWC and esbuild require
  • No emit: TypeScript only type-checks, and bundlers produce the output

Strictest config

Adds these checks on top of strict: true:

  • noFallthroughCasesInSwitch: prevents fallthrough in switch statements
  • noImplicitOverride: requires the override keyword
  • noImplicitReturns: every code path must return
  • noUnusedLocals: no unused local variables
  • noUnusedParameters: no unused function parameters
  • noUncheckedIndexedAccess: indexed access returns T | undefined
  • allowUnreachableCode: false: unreachable code is an error
  • allowUnusedLabels: false: unused labels are an error

Next.js config

On top of the React config, the Next.js config:

  • Registers the next TypeScript plugin for App Router type safety
  • Includes next-env.d.ts and .next/types/**/*.ts for generated types
  • Includes every *.ts and *.tsx file under the project root

Type checking

Run type checking across all packages:

pnpm types:check

Or for a specific package:

pnpm turbo run types:check --filter @zeno-lib/ui