install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/ts-strict-mode" ~/.claude/skills/intense-visions-harness-engineering-ts-strict-mode && rm -rf "$T"
manifest:
agents/skills/claude-code/ts-strict-mode/SKILL.mdsource content
TypeScript Strict Mode
Enable and satisfy strict TypeScript checks including strictNullChecks and exactOptionalPropertyTypes
When to Use
- Starting a new TypeScript project (always enable strict mode from day one)
- Migrating an existing project to stricter type checking
- Debugging type errors caused by strict flags
- Deciding which individual strict flags to enable during incremental adoption
Instructions
- Enable
instrict: true
— this activates all strict flags at once:tsconfig.json
{ "compilerOptions": { "strict": true } }
-
What
enables:strict: true
—strictNullChecks
andnull
are not assignable to other typesundefined
— function parameter types are checked contravariantlystrictFunctionTypes
—strictBindCallApply
,bind
,call
are fully typedapply
— class properties must be initializedstrictPropertyInitialization
— untyped variables/parameters are errors, notnoImplicitAnyany
—noImplicitThis
must have a type in function bodiesthis
— emitsalwaysStrict
in every file"use strict"
— catch variables areuseUnknownInCatchVariables
, notunknownany
-
Handle
— the most impactful flag. Check for null before accessing:strictNullChecks
function getUser(id: string): User | null { /* ... */ } const user = getUser('123'); // user.name; // Error: Object is possibly 'null' if (user) { user.name; // OK — narrowed to User }
- Handle
— add explicit types where inference fails:noImplicitAny
// Error: Parameter 'item' implicitly has an 'any' type function process(item) { /* ... */ } // Fixed function process(item: unknown) { /* ... */ }
- Handle
— initialize class properties:strictPropertyInitialization
class Service { // Error: Property 'db' has no initializer private db: Database; // Fix 1: Initialize in constructor constructor(db: Database) { this.db = db; } // Fix 2: Definite assignment assertion (use sparingly) private db!: Database; }
- Handle
:useUnknownInCatchVariables
try { await fetchData(); } catch (error) { // error is 'unknown', not 'any' if (error instanceof Error) { console.log(error.message); } }
- Additional strict flags beyond
:strict: true
{ "compilerOptions": { "strict": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "noPropertyAccessFromIndexSignature": true } }
— index signatures includenoUncheckedIndexedAccess
:undefined
const map: Record<string, string> = { a: 'hello' }; // Without flag: map['b'] is string // With flag: map['b'] is string | undefined
- Incremental strict adoption — enable flags one at a time:
{ "compilerOptions": { "strict": false, "strictNullChecks": true, "noImplicitAny": true } }
Fix errors per flag before enabling the next.
Details
Strict mode catches entire categories of bugs at compile time: null dereferences, implicit
any types, uninitialized properties, and unsafe function calls. The upfront cost of fixing strict errors pays back quickly in reduced runtime bugs.
is not included in noUncheckedIndexedAccess
strict: true but is one of the most valuable additional flags. It forces you to handle the case where an array index or object key might not exist, preventing undefined is not a function errors.
distinguishes between "property is missing" and "property is exactOptionalPropertyTypes
undefined". With this flag, { name?: string } means the property may be absent, but if present it must be a string (not undefined).
Strict migration strategy:
- Enable
and count the errorsstrict: true - If manageable (<100), fix them all at once
- If large (>100), disable
and enable flags individually:strict
first (most errors), thennoImplicitAny
, then the reststrictNullChecks - Use
temporarily for errors you cannot fix immediately — track them with a lint rule// @ts-expect-error
Trade-offs:
- Strict mode increases type annotation verbosity — but reduces debugging time
causes the most migration pain — but prevents the most common runtime error (null dereference)strictNullChecks
addsnoUncheckedIndexedAccess
to every index access — use non-null assertion (| undefined
) or destructuring with defaults for known-safe accesses!- Third-party libraries with loose types can produce cascading strict errors — use declaration merging to fix them locally
Source
https://typescriptlang.org/tsconfig#strict
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.