Ts tsconfig modern strict starter
Skill kongyo2/agent-primary-ts-starters-src/skills/ts-tsconfig-modern-strict-starter
npx -y skills add kongyo2/agent-primary-ts-starters-src --skill ts-tsconfig-modern-strict-starterAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Set up a TypeScript tsconfig.json with modern (ESNext + bundler/nodenext) and maximally strict settings, tuned so that `tsc --noEmit` becomes a fast, reliable inner feedback loop for the LLM agent doing the editing. Use whenever a tsconfig.json is being created, edited, reviewed, troubleshot, or even just discussed — apply the standing policy even when the user only asks about a single option. Default to this skill instead of free-recall whenever the answer involves a tsconfig field.
SKILL.md
9.8 KB, as published. Nobody here has run it
TS + npm tsconfig Modern Strict Starter (Agent-Friendly)
Use whenever a tsconfig.json is being created, edited, reviewed, or troubleshot in a TypeScript npm project. In a monorepo, edit the workspace the user names — ask if it isn't named.
The standing policy below is tuned so that tsc --noEmit is the LLM agent's primary inner feedback loop. Modern syntax + maximum strictness narrows the surface where an agent can ship a silent bug; explicit module resolution removes whole classes of "why isn't this importing" turns that would otherwise burn agent context; incremental: true keeps the loop fast enough to run between each edit.
Standing Policy (override only with a stated reason)
"target": "esnext". Downleveling is the bundler / runtime's job, not tsc's."strict": trueplus every recommended add-on flag below."moduleResolution": "bundler"for app code via a bundler;"nodenext"for code running on Node directly."skipLibCheck": true. Always — a single broken.d.tsinnode_modulesotherwise stops the entire feedback loop."incremental": true(or"composite": trueunder project references). The.tsbuildinfocache makes the second-and-onwardtsc --noEmitrun near-instant, which is what keeps the agent loop tight enough to run between edits."isolatedModules": trueand"verbatimModuleSyntax": truefor any code touched by esbuild / SWC / Babel / Vite.
When the user proposes loosening any of these, ask what concrete problem they are solving before agreeing.
Pick the Use Case First
Resolve the use case before writing or modifying a tsconfig — the four templates differ in incompatible ways.
Is tsc emitting JS?
├── No, a bundler emits ─────────────────► §1 Browser app + bundler
└── Yes, tsc emits
├── Running on Node directly (ESM) ──► §2 Node ESM app
└── Publishing to npm
├── Single package ────► §3 Library
└── Monorepo ────► §4 Project references
The target / module / moduleResolution Trio
Co-dependent. Pick one row, don't improvise.
| Scenario | target | module | moduleResolution |
|---|---|---|---|
| Browser app via bundler | esnext | esnext | bundler |
| Node.js native ESM | esnext | nodenext | nodenext |
| Publishable library (build via tsc) | es2020+ | esnext | bundler |
| Node.js CommonJS (legacy) | es2022 | commonjs | node |
Common mismatches:
module: "commonjs"+moduleResolution: "bundler"— invalid combination.nodenext+ extensionless relative imports — Node ESM requires.json relative imports even when the source is.ts.
§1. Browser app + bundler (Vite, Next.js, Rspack, etc.)
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["esnext", "dom", "dom.iterable"],
"jsx": "react-jsx",
"noEmit": true,
"incremental": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"resolveJsonModule": true,
"allowImportingTsExtensions": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false
},
"include": ["src"]
}
Drop "dom" and "dom.iterable" from lib for non-browser code. Change jsx to "preserve" plus jsxImportSource for Preact / Solid.
§2. Node.js ESM application
package.json must have "type": "module". Relative imports require .js even when the source is .ts.
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"moduleResolution": "nodenext",
"lib": ["esnext"],
"outDir": "./dist",
"rootDir": "./src",
"sourceMap": true,
"incremental": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true
},
"include": ["src/**/*"],
"exclude": ["**/*.test.ts", "**/*.spec.ts", "dist"]
}
§3. Publishable library
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "bundler",
"rootDir": "./src",
"outDir": "./dist",
"declarationDir": "./dist-types",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"incremental": true,
"allowImportingTsExtensions": false,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true
},
"include": ["src/**/*"],
"exclude": ["**/*.test.ts", "**/*.spec.ts"]
}
When publishing, also configure package.json exports — the types field must come first inside each conditional block.
§4. Monorepo with project references
Root tsconfig.json:
{
"files": [],
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/utils" },
{ "path": "./packages/app" }
]
}
Each package extends a shared base and sets composite: true:
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"rootDir": "./src",
"outDir": "./dist",
"declaration": true,
"declarationMap": true
},
"include": ["src/**/*"],
"references": [{ "path": "../core" }]
}
Build with tsc --build (or tsc -b). Plain tsc against the root won't resolve references.
Strict Flags Beyond strict: true
These are not enabled by strict: true but should be on by default for an agent-primary workflow:
noUncheckedIndexedAccess—arr[i]andobj[k]becomeT | undefined. Catches a class of silent index bugs that agents emit easily.exactOptionalPropertyTypes—?:no longer accepts an explicitundefined.noImplicitOverride— subclass overrides must sayoverride.noImplicitReturns— all branches return when any branch does.noFallthroughCasesInSwitch— no silent fallthrough.noUnusedLocals/noUnusedParameters— agent leftovers get caught at type-check. For unused parameters in interface implementations, prefix with_instead of disabling the flag globally.allowUnreachableCode: false/allowUnusedLabels: false— treat as errors, not warnings.
When the toolchain supports it, also add verbatimModuleSyntax (any non-tsc transpiler), isolatedDeclarations (TS 5.5+ library), erasableSyntaxOnly (TS 5.8+ type-strip runtime).
Agent Inner Loop
Add to package.json so the agent has a single command for the type-check feedback loop:
{
"scripts": {
"typecheck": "tsc --noEmit",
"typecheck:watch": "tsc --noEmit --watch"
}
}
With incremental: true set, the second-and-later npm run typecheck returns in well under a second on typical projects — which is what makes this usable as an inner loop the agent runs between edits. When typecheck already targets another tool, leave it untouched and add typecheck:tsc alongside.
When a Setting "Isn't Working", Show the Resolved Config
npx tsc --showConfig
Prints the fully resolved config after all extends. The single most useful command when a setting "isn't working" — run it before guessing.
Merge Rules for an Existing tsconfig
When tsconfig.json already exists, do not overwrite. Surface the diff against the matching template above, flag any standing-policy violations (strict: false, skipLibCheck: false, trio mismatch), and let the user decide whether to migrate. Recommended migration order to minimize churn:
strict: truenoUnusedLocals+noUnusedParametersnoImplicitReturns+noFallthroughCasesInSwitchnoUncheckedIndexedAccessexactOptionalPropertyTypesverbatimModuleSyntax
Run npm run typecheck after each step. Commit between steps.
Verification
npx tsc --noEmitexits 0 on the project after the chosen template is applied (or surfaces real type errors that should be fixed).npx tsc --showConfigprints a resolved config matching the standing policy.
References
- TypeScript compiler options: https://www.typescriptlang.org/tsconfig
- TypeScript modules guide: https://www.typescriptlang.org/docs/handbook/modules/introduction.html