typescript-config
tsconfig.json shape for ESM/gradle Hub modules. Use when configuring TypeScript or diagnosing build errors.
SKILL.md.claude/skills/typescript-config/SKILL.md
GitHubtsconfig.json
The generator scaffolds the canonical tsconfig.json. Every module uses the same shape; agents validate against it and refuse to edit it without a documented reason.
Canonical shape
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"noImplicitAny": false,
"target": "ES2022",
"strict": true,
"removeComments": true,
"sourceMap": true,
"noLib": false,
"allowJs": true,
"declaration": true,
"lib": ["ES2022"],
"outDir": "dist",
"typeRoots": ["node_modules/@types"],
"esModuleInterop": true,
"useUnknownInCatchVariables": false
},
"include": ["src/**/*", "test/**/*", "generated/**/*"],
"exclude": ["dist", "node_modules"]
}
That's what yo @zerobias-org/module writes. If a module on disk differs, either it predates the current generator or it's been edited — both worth flagging.
Why each setting matters
| Setting | Reason |
|---|---|
module: NodeNext + moduleResolution: NodeNext |
ESM. Required so the compiler honors "type": "module" and the .js-suffixed imports. |
target: ES2022 / lib: ["ES2022"] |
Matches Node 22 runtime. No down-leveling. |
strict: true |
All strict flags. Module code must compile cleanly under this. |
noImplicitAny: false |
Relaxed for generated code (the codegen emits some loose types). |
useUnknownInCatchVariables: false |
Keeps catch (e) typed as any to match the @zerobias-org/types-core error pattern. |
declaration: true |
Generates .d.ts files into dist/ so the npm consumer gets types. |
sourceMap: true |
Stack traces from zbb testDirect point back to TypeScript source. |
outDir: "dist" |
Gradle's compile task expects this; package.json's main is dist/src/index.js. |
esModuleInterop: true + allowJs: true |
Required for some legacy CJS deps that still appear under node_modules. |
typeRoots: ["node_modules/@types"] |
Explicit because no workspace hoisting — each module has its own node_modules. |
include: src + test + generated |
Compile sources, tests, and codegen output. Omit any and the compile fails. |
exclude: dist + node_modules |
Prevents double-compilation of build output and dependency code. |
What's deliberately absent
skipLibCheck— not enabled. The generator's deps are pinned to versions that pass strict checking. If a dep update introduces@typeserrors, fix the dep, don't paper over it.paths/baseUrl— relative imports only. Path aliases interact badly with the codegen andtsx/esm.incremental/tsBuildInfoFile— gradle caches the compile task; an additional layer of incremental state is just one more thing to invalidate.experimentalDecorators/emitDecoratorMetadata— no decorators in module code today. Add only if a specific module actually uses them, and document why in a PR.resolveJsonModule— none of the generator's stubs need it. Add per-module with a comment if you genuinely need to import*.json.hub-sdkinexclude— not needed.hub-sdk/is a sibling npm package with its owntsconfig.json(gitignored, written by gradle's generate task). The rootincludepatterns don't reach into it.
When to deviate
Almost never. Valid reasons:
- Module legitimately needs a feature absent from this template (e.g.
resolveJsonModule) - A dep ships broken types and you need a targeted exclude
In both cases:
- Add the option with a
//comment explaining why - Reference the gradle task that needs it (
compileTs, etc.) - Mention it in the PR description
ESM import discipline (enforced by module: NodeNext)
Relative imports must end in .js:
import { FooImpl } from './FooImpl.js';
import { Bar } from '../generated/model/index.js';
Package imports do not:
import { LoggerEngine } from '@zerobias-org/logger';
tsx/esm (used by .mocharc.json) honors the same rules at test time.
Quick validation
# Generator-canonical fields
jq -r '.compilerOptions | "module=\(.module) target=\(.target) strict=\(.strict)"' tsconfig.json
# Expect: module=NodeNext target=ES2022 strict=true
# Includes generated/ and test/
jq -r '.include[]' tsconfig.json
# Expect: src/**/* test/**/* generated/**/*
# tsc dry-run (gradle handles real compile)
npx tsc --noEmit
Common issues
Cannot find module './Foo' or its corresponding type declarations— relative import missing.jsextension. Run the audit grep in@.claude/skills/tool-requirements/SKILL.md.Cannot find name 'describe'—@types/mochamissing ortypeRootsremoved. Restore the canonicaltypeRootsline.Module '"@zerobias-org/util-connector"' has no exported member 'ConnectionMetadata'—ConnectionMetadata/ConnectionStatuslive in@zerobias-org/types-core-js, notutil-connector. Update the import.Cannot use import statement outside a module—package.jsonis missing"type": "module". Add it (the generator template always includes it).
Related
- @.claude/skills/module-exports/SKILL.md —
src/index.tsshape (re-exports + factory) - @.claude/skills/tool-requirements/SKILL.md —
zbb compileand audit greps