Strict Checks

We recommend using the compiler option strict to opt-in to every possible improvement as they are built.

TypeScript supports a wide spectrum of JavaScript patterns and defaults to allowing for quite a lot of flexibility in accommodating these styles. Often the safety and potential scalability of a codebase can be at odds with some of these techniques.

Because of the variety of supported JavaScript, upgrading to a new version of TypeScript can uncover two types of errors:

  • Errors which already exist in your codebase, which TypeScript has uncovered because the language has refined its understanding of JavaScript.
  • A new suite of errors which tackle a new problem domain.

TypeScript will usually add a compiler flag for the latter set of errors, and by default these are not enabled.

Always Strict - alwaysStrict

Ensures that your files are parsed in the ECMAScript strict mode, and emit “use strict” for each source file.

ECMAScript strict mode was introduced in ES5 and provides behavior tweaks to the runtime of the JavaScript engine to improve performance, and makes a set of errors throw instead of silently ignoring them.

  • Recommended:

    True

  • Default:

    false, unless strict is set

  • Related:

    strict

  • Released:

    2.1

No Implicit Any - noImplicitAny

In some cases where no type annotations are present, TypeScript will fall back to a type of any for a variable when it cannot infer the type.

This can cause some errors to be missed, for example:

  1. function fn(s) {
    // No error?
    console.log(s.subtr(3));
    }
    fn(42);
    Try

Turning on noImplicitAny however TypeScript will issue an error whenever it would have inferred any:

  1. function fn(s) {
    Parameter 's' implicitly has an 'any' type.7006Parameter 's' implicitly has an 'any' type.
    console.log(s.subtr(3));
    }
    Try
  • Recommended:

    True

  • Default:

    false, unless strict is set

  • Related:

    strict

No Implicit This - noImplicitThis

Raise error on ‘this’ expressions with an implied ‘any’ type.

For example, the class below returns a function which tries to access this.width and this.height – but the context for this inside the function inside getAreaFunction is not the instance of the Rectangle.

  1. class Rectangle {
    width: number;
    height: number;
  2. constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
    }
  3. getAreaFunction() {
    return function () {
    return this.width * this.height;
    'this' implicitly has type 'any' because it does not have a type annotation.
    'this' implicitly has type 'any' because it does not have a type annotation.2683
    2683'this' implicitly has type 'any' because it does not have a type annotation.
    'this' implicitly has type 'any' because it does not have a type annotation.
    };
    }
    }
    Try
  • Recommended:

    True

  • Default:

    false, unless strict is set

  • Related:

    strict

  • Released:

    2.0

Strict - strict

The strict flag enables a wide range of type checking behavior that results in stronger guarantees of program correctness. Turning this on is equivalent to enabling all of the strict mode family options, which are outlined below. You can then turn off individual strict mode family checks as needed.

Future versions of TypeScript may introduce additional stricter checking under this flag, so upgrades of TypeScript might result in new type errors in your program. When appropriate and possible, a corresponding flag will be added to disable that behavior.

Strict Bind Call Apply - strictBindCallApply

When set, TypeScript will check that the built-in methods of functions call, bind, and apply are invoked with correct argument for the underlying function:

  1. // With strictBindCallApply on
    function fn(x: string) {
    return parseInt(x);
    }
  2. const n1 = fn.call(undefined, "10");
  3. const n2 = fn.call(undefined, false);
    Argument of type 'boolean' is not assignable to parameter of type 'string'.2345Argument of type 'boolean' is not assignable to parameter of type 'string'.
    Try

Otherwise, these functions accept any arguments and will return any:

  1. // With strictBindCallApply off
    function fn(x: string) {
    return parseInt(x);
    }
  2. // Note: No error; return type is 'any'
    const n = fn.call(undefined, false);
    Try
  • Recommended:

    True

  • Default:

    false, unless strict is set

  • Related:

    strict

  • Released:

    3.2

Strict Function Types - strictFunctionTypes

When enabled, this flag causes functions parameters to be checked more correctly.

Here’s a basic example with strictFunctionTypes off:

  1. function fn(x: string) {
    console.log("Hello, " + x.toLowerCase());
    }
  2. type StringOrNumberFunc = (ns: string | number) => void;
  3. // Unsafe assignment
    let func: StringOrNumberFunc = fn;
    // Unsafe call - will crash
    func(10);
    Try

With strictFunctionTypes on, the error is correctly detected:

  1. function fn(x: string) {
    console.log("Hello, " + x.toLowerCase());
    }
  2. type StringOrNumberFunc = (ns: string | number) => void;
  3. // Unsafe assignment is prevented
    let func: StringOrNumberFunc = fn;
    Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'.
  4. Types of parameters 'x' and 'ns' are incompatible.
  5. Type 'string | number' is not assignable to type 'string'.
  6. Type 'number' is not assignable to type 'string'.2322Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'.
  7. Types of parameters 'x' and 'ns' are incompatible.
  8. Type 'string | number' is not assignable to type 'string'.
  9. Type 'number' is not assignable to type 'string'.Try

During development of this feature, we discovered a large number of inherently unsafe class hierarchies, including some in the DOM. Because of this, the setting only applies to functions written in function syntax, not to those in method syntax:

  1. type Methodish = {
    func(x: string | number): void;
    };
  2. function fn(x: string) {
    console.log("Hello, " + x.toLowerCase());
    }
  3. // Ultimately an unsafe assignment, but not detected
    const m: Methodish = {
    func: fn,
    };
    m.func(10);
    Try
  • Recommended:

    True

  • Default:

    false, unless strict is set

  • Related:

    strict

  • Released:

    2.6

Strict Null Checks - strictNullChecks

When strictNullChecks is false, null and undefined are effectively ignored by the language. This can lead to unexpected errors at runtime.

When strictNullChecks is true, null and undefined have their own distinct types and you’ll get a type error if you try to use them where a concrete value is expected.

For example with this TypeScript code, users.find has no guarantee that it will actually find a user, but you can write code as though it will:

  1. declare const loggedInUsername: string;
  2. const users = [
    { name: "Oby", age: 12 },
    { name: "Heera", age: 32 },
    ];
  3. const loggedInUser = users.find((u) => u.name === loggedInUsername);
    console.log(loggedInUser.age);
    Try

Setting strictNullChecks to true will raise an error that you have not made a guarantee that the loggedInUser exists before trying to use it.

  1. declare const loggedInUsername: string;
  2. const users = [
    { name: "Oby", age: 12 },
    { name: "Heera", age: 32 },
    ];
  3. const loggedInUser = users.find((u) => u.name === loggedInUsername);
    console.log(loggedInUser.age);
    Object is possibly 'undefined'.2532Object is possibly 'undefined'.
    Try

The second example failed because the array’s find function looks a bit like this simplification:

  1. ts
    // When strictNullChecks: true
    type Array = {
    find(predicate: (value: any, index: number) => boolean): S | undefined;
    };
    // When strictNullChecks: false the undefined is removed from the type system,
    // allowing you to write code which assumes it always found a result
    type Array = {
    find(predicate: (value: any, index: number) => boolean): S;
    };
  • Recommended:

    True

  • Default:

    false, unless strict is set

  • Related:

    strict

  • Released:

    2.0

Strict Property Initialization - strictPropertyInitialization

When set to true, TypeScript will raise an error when a class property was declared but not set in the constructor.

  1. class UserAccount {
    name: string;
    accountType = "user";
  2. email: string;
    Property 'email' has no initializer and is not definitely assigned in the constructor.2564Property 'email' has no initializer and is not definitely assigned in the constructor.
    address: string | undefined;
  3. constructor(name: string) {
    this.name = name;
    // Note that this.email is not set
    }
    }
    Try

In the above case:

  • this.name is set specifically.
  • this.accountType is set by default.
  • this.email is not set and raises an error.
  • this.address is declared as potentially undefined which means it does not have to be set.

  • Recommended:

    True

  • Default:

    false, unless strict is set

  • Related:

    strict

  • Released:

    2.7