jsconfig.json option

strict

  • Default false
  • Since TypeScript 2.3

strict is a shorthand. It turns on a family of checks that can each be set on their own: in TypeScript 5.9 that is noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, strictBuiltinIteratorReturn, noImplicitThis, useUnknownInCatchVariables and alwaysStrict.

In a JavaScript project the two that change the most are noImplicitAny, which makes every untyped parameter an error (TS7006), and strictNullChecks, which makes you handle null and undefined. TypeScript 6.0 makes strict the default, so write it either way to keep a config meaning the same thing across versions.

At a glance

Write "strict": true for new code; on an existing codebase, start without it and turn it on once the first errors are fixed
On the command line --strict
Type boolean
Default in TypeScript 5.9 false
Default from TypeScript 6.0 true (TypeScript 6.0)
TypeScript's description Enable all strict type-checking options.
In the quick-start setups
Generator, relaxed false
Generator, recommended true
Generator, strict true

The description is quoted from TypeScript's own option list (Apache-2.0); see the notices. The setup values are the checked configs on the quick-start pages. The generator rows are what the jsconfig generator writes at each level.

Examples

main.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: main.js(10,23): error TS7006: Parameter 'name' implicitly has an 'any' type. main.js(17,13): error TS18048: 'user' is possibly 'undefined'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. main.js(10,23): error TS7006: Parameter 'name' implicitly has an 'any' type. main.js(17,13): error TS18048: 'user' is possibly 'undefined'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. main.js(10,23): error TS7006: Parameter 'name' implicitly has an 'any' type. main.js(17,13): error TS18048: 'user' is possibly 'undefined'. checked 21 October 2026
/**
 * @param {{ id: number, name: string }[]} users
 * @param {number} id
 */
export function findUser(users, id) {
  return users.find((u) => u.id === id);
}

export function greet(name) {error TS7006: Parameter 'name' implicitly has an 'any' type.
  return `Hello, ${name}`;
}

const users = [{ id: 1, name: "Ada" }];
const user = findUser(users, 2);
console.log(user.name);error TS18048: 'user' is possibly 'undefined'.
strict on: an untyped parameter and a lookup that may find nothing.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": [
    "*.js"
  ]
}
main.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
/**
 * @param {{ id: number, name: string }[]} users
 * @param {number} id
 */
export function findUser(users, id) {
  return users.find((u) => u.id === id);
}

export function greet(name) {
  return `Hello, ${name}`;
}

const users = [{ id: 1, name: "Ada" }];
const user = findUser(users, 2);
console.log(user.name);
strict off: the same code passes.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": false,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": [
    "*.js"
  ]
}

What strict turns on

Each member except strictBuiltinIteratorReturn has its own page with the same code checked both ways:

Turning one check back off

An option you set yourself wins over strict. "strict": true with "strictPropertyInitialization": false keeps every strict check except that one. That is a reasonable middle step for a codebase with many classes, and the order you list them in does not matter.

jsconfig.json
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    // every strict check except this one
    "strictPropertyInitialization": false
  }
}

The family grows

New TypeScript releases add checks to strict: useUnknownInCatchVariables joined in 4.4 and strictBuiltinIteratorReturn in 5.6. Upgrading TypeScript can therefore report errors in code that passed before, without any change to your config. Read the release notes of each minor version before you move to it.

Stricter options that strict leaves off

These are not part of strict and are worth considering once it passes: noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitReturns, noFallthroughCasesInSwitch, noImplicitOverride, noUnusedLocals and noUnusedParameters, noPropertyAccessFromIndexSignature and noUncheckedSideEffectImports. The strict level of the jsconfig generator adds the first four.

Gotchas

  • Without strict, a .js file is checked loosely: untyped parameters are any without complaint and null fits any type. Code can pass npm run lint and still fail on the first undefined.
  • A config with no strict line means false in TypeScript 5.9 and true in 6.0. Write the line.

Questions

Should I turn on strict in an existing JavaScript project?

Eventually. Start with checkJs alone, fix what it finds, then turn on strict (or noImplicitAny first, since it reports the most). The checkJs page describes the order.

Is strict on by default?

Not in TypeScript 5.9, where it defaults to false. TypeScript 6.0 changes the default to true.

Sources

Last reviewed 20 October 2026.