--- title: TypeScript Config description: The shared compiler options, and the alias everything resolves through. type: reference related: - /en/docs/structure - /en/docs/packages/testing --- # TypeScript Config Three configs, extended by every app and package: ```json title="apps/app/tsconfig.json" { "extends": "@kreogen/typescript-config/nextjs.json" } ``` | Config | For | | -------------------- | -------------------------------------------------- | | `base.json` | Everything. Strict, ES2022, NodeNext | | `nextjs.json` | Apps and any package importing React in a Next app | | `react-library.json` | A React library compiled outside Next | ## The alias `nextjs.json` is where `@kreogen/*` becomes resolvable: ```json "paths": { "@/*": ["./*"], "@kreogen/*": ["../../packages/*"] } ``` That single line is why packages need no `exports` map and no build step: `@kreogen/auth/session` resolves directly to `packages/auth/session.ts`. This path is written relative to an app directory, two levels below the workspace root. It is duplicated in `@kreogen/testing`, which every test run reads, and the two must agree — a test fails when they drift, because nothing else would tell you. TypeScript reports a missing module and explains nothing about why. The consequence is worth restating: **renaming a file in a package is a breaking API change.** There is no indirection between the import specifier and the file on disk. ## Strictness worth knowing about Beyond `strict: true`, four options are on that many projects leave off: **`noUncheckedIndexedAccess`.** `array[0]` is `T | undefined`, and `record[key]` likewise. This is the one that produces the most friction and prevents the most bugs — a `Record` is typed as total but is not, so an index that misses yields `undefined` and arithmetic on it silently produces `NaN`. That exact failure reached a rate limiter's window calculation here before this was enabled. **`noUnusedLocals` and `noUnusedParameters`.** A dead variable is usually the residue of a half-finished edit. Prefix a genuinely unused parameter with `_`. **`noFallthroughCasesInSwitch`.** Fallthrough is almost always a missing `break`, and webhook handlers are full of switches. **`isolatedModules`.** Each file must be transpilable alone, which is what bundlers actually do. It forces `import type` for type-only imports — annoying until the first time a type import fails to be erased and drags a whole module into a client bundle. ## Typecheck ```sh bun run typecheck ``` Every app and package runs `tsc --noEmit`. In turbo this depends on `^build`, because packages need the generated Prisma client before they will typecheck at all — and `@kreogen/database` additionally depends on its own build, since it generates that client. The apps set `noEmit: true` and `declaration: false`: Next does the compiling, and `tsc` is only ever asked whether the code is correct. --- For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md) For an index of all available documentation, see [/llms.txt](/llms.txt)