Maximally strict, deliberately pedantic TypeScript configurations, built for TypeScript 7.
Three configs: a base carrying every checking rule, plus node and react variants that extend it and add only what their runtime requires.
The premise: every rule here converts a class of runtime bug into a compile error. The configs are opinionated on purpose — if a rule only ever produced noise, it isn't in here.
npm install --save-dev @moonstar-x/tsconfig typescripttypescript >= 6.0.0 is a required peer dependency (the configs use target/lib es2025, which TypeScript 6.0 was the first release to accept). The node variant additionally needs @types/node:
npm install --save-dev @types/nodeExtend the variant you need, then add your own paths. This package intentionally sets no path options (outDir, rootDir, include, exclude, paths, baseUrl).
{
"extends": "@moonstar-x/tsconfig/node",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}{
"extends": "@moonstar-x/tsconfig/react",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}For a runtime-agnostic package, or as a starting point for your own variant:
{
"extends": "@moonstar-x/tsconfig",
"compilerOptions": { "outDir": "./dist", "rootDir": "./src" },
"include": ["src/**/*"]
}These are intentional. Each is listed with its escape hatch.
isolatedDeclarationsdemands explicit types on exports.export const v = Math.max(1, 2)fails with TS9010; writeexport const v: number = …. Trivially-inferrable initializers (export const f = () => 1) are still fine. React components need an explicit return type:
export function Counter(props: CounterProps): JSX.Element { … }Escape hatch: "isolatedDeclarations": false. This is the first flag to drop for an application (as opposed to a published library).
erasableSyntaxOnlybansenumandnamespace. Use a const object plus a union type:
export const Color = { Red: "red", Blue: "blue" } as const;
export type Color = (typeof Color)[keyof typeof Color];-
verbatimModuleSyntaxrequiresimport type. A type imported without it is a compile error (TS1484) rather than a silent elision. -
nodenextrequires runtime extensions in ESM. In a"type": "module"package, writeimport { x } from "./x.js"even though the file isx.ts. That's Node's rule, not TypeScript's. -
skipLibCheck: falsechecks your dependencies' types. This finds real problems, but one broken@typespackage can block your build. Escape hatch:"skipLibCheck": true. -
exactOptionalPropertyTypesrejects explicitundefined. To allow it, declare it:{ a?: string | undefined }. -
noUncheckedIndexedAccessmakes every index access possibly-undefined. That is the point. Narrow it, or use.at()and handle theundefined.