Skip to content
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here

Type Checking

allowUnreachableCode

When:

  • undefined (default) provide suggestions as warnings to editors
  • true unreachable code is ignored
  • false raises compiler errors about unreachable code

These warnings are only about code which is provably unreachable due to the use of JavaScript syntax, for example:

ts
function fn(n: number) {
  if (n > 5) {
    return true;
  } else {
    return false;
  }
  return true;
}

With "allowUnreachableCode": false:

ts
function 
fn
(
n
: number) {
if (
n
> 5) {
return true; } else { return false; } return true;
Unreachable code detected.
}
Try

This does not affect errors on the basis of code which appears to be unreachable due to type analysis.

allowUnusedLabels

When:

  • undefined (default) provide suggestions as warnings to editors
  • true unused labels are ignored
  • false raises compiler errors about unused labels

Labels are very rare in JavaScript and typically indicate an attempt to write an object literal:

ts
function 
verifyAge
(
age
: number) {
// Forgot 'return' statement if (
age
> 18) {
verified: true;
Unused label.
} }
Try

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.

exactOptionalPropertyTypes Recommended

With exactOptionalPropertyTypes enabled, TypeScript applies stricter rules around how it handles properties on type or interfaces which have a ? prefix.

For example, this interface declares that there is a property which can be one of two strings: 'dark' or 'light' or it should not be in the object.

ts
interface UserDefaults {
  // The absence of a value represents 'system'
  colorThemeOverride?: "dark" | "light";
}

Without this flag enabled, there are three values which you can set colorThemeOverride to be: "dark", "light" and undefined.

Setting the value to undefined will allow most JavaScript runtime checks for the existence to fail, which is effectively falsy. However, this isn't quite accurate; colorThemeOverride: undefined is not the same as colorThemeOverride not being defined. For example, "colorThemeOverride" in settings would have different behavior with undefined as the key compared to not being defined.

exactOptionalPropertyTypes makes TypeScript truly enforce the definition provided as an optional property:

ts
const 
settings
=
getUserSettings
();
settings
.
colorThemeOverride
= "dark";
settings
.
colorThemeOverride
= "light";
// But not: settings.colorThemeOverride =
undefined
;
Type 'undefined' is not assignable to type '"dark" | "light"' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.
Try

noFallthroughCasesInSwitch

Report errors for fallthrough cases in switch statements. Ensures that any non-empty case inside a switch statement includes either break, return, or throw. This means you won't accidentally ship a case fallthrough bug.

ts
const 
a
: number = 6;
switch (
a
) {
case 0:
Fallthrough case in switch.
console
.
log
("even");
case 1:
console
.
log
("odd");
break; }
Try

noImplicitAny Recommended

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:

ts
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:

ts
function 
fn
(s) {
Parameter 's' implicitly has an 'any' type.
console
.
log
(
s
.subtr(3));
}
Try

noImplicitOverride

When working with classes which use inheritance, it's possible for a sub-class to get "out of sync" with the functions it overloads when they are renamed in the base class.

For example, imagine you are modeling a music album syncing system:

ts
class 
Album
{
download
() {
// Default behavior } } class
SharedAlbum
extends
Album
{
download
() {
// Override to get info from many sources } }
Try

Then when you add support for machine-learning generated playlists, you refactor the Album class to have a 'setup' function instead:

ts
class 
Album
{
setup
() {
// Default behavior } } class
MLAlbum
extends
Album
{
setup
() {
// Override to get info from algorithm } } class
SharedAlbum
extends
Album
{
download
() {
// Override to get info from many sources } }
Try

In this case, TypeScript has provided no warning that download on SharedAlbum expected to override a function in the base class.

Using noImplicitOverride you can ensure that the sub-classes never go out of sync, by ensuring that functions which override include the keyword override.

The following example has noImplicitOverride enabled, and you can see the error received when override is missing:

ts
class 
Album
{
setup
() {}
} class
MLAlbum
extends
Album
{
override
setup
() {}
} class
SharedAlbum
extends
Album
{
setup() {}
This member must have an 'override' modifier because it overrides a member in the base class 'Album'.
}
Try

noImplicitReturns

When enabled, TypeScript will check all code paths in a function to ensure they return a value.

ts
function 
lookupHeadphonesManufacturer
(
color
: "blue" | "black"): string {
Function lacks ending return statement and return type does not include 'undefined'.
if (
color
=== "blue") {
return "beats"; } else { "bose"; } }
Try

noImplicitThis Recommended

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.

ts
class 
Rectangle
{
width
: number;
height
: number;
constructor(
width
: number,
height
: number) {
this.
width
=
width
;
this.
height
=
height
;
}
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.
}; } }
Try

noPropertyAccessFromIndexSignature

This setting ensures consistency between accessing a field via the "dot" (obj.key) syntax, and "indexed" (obj["key"]) and the way which the property is declared in the type.

Without this flag, TypeScript will allow you to use the dot syntax to access fields which are not defined:

ts
interface GameSettings {
  // Known up-front properties
  
speed
: "fast" | "medium" | "slow";
quality
: "high" | "low";
// Assume anything unknown to the interface // is a string. [
key
: string]: string;
} const
settings
=
getSettings
();
settings
.
speed
;
settings
.
quality
;
// Unknown key accessors are allowed on // this object, and are `string`
settings
.
username
;
Try

Turning the flag on will raise an error because the unknown field uses dot syntax instead of indexed syntax.

ts
const 
settings
=
getSettings
();
settings
.
speed
;
settings
.
quality
;
// This would need to be settings["username"];
settings
.
username
;
Property 'username' comes from an index signature, so it must be accessed with ['username'].
Try

The goal of this flag is to signal intent in your calling syntax about how certain you are this property exists.

noUncheckedIndexedAccess

TypeScript has a way to describe objects which have unknown keys but known values on an object, via index signatures.

ts
interface EnvironmentVars {
  
NAME
: string;
OS
: string;
// Unknown properties are covered by this index signature. [
propName
: string]: string;
} declare const
env
: EnvironmentVars;
// Declared as existing const
sysName
=
env
.
NAME
;
const
os
=
env
.
OS
;
// Not declared, but because of the index // signature, then it is considered a string const
nodeEnv
=
env
.
NODE_ENV
;
Try

Turning on noUncheckedIndexedAccess will add undefined to any un-declared field in the type.

ts
declare const 
env
: EnvironmentVars;
// Declared as existing const
sysName
=
env
.
NAME
;
const
os
=
env
.
OS
;
// Not declared, but because of the index // signature, then it is considered a string const
nodeEnv
=
env
.
NODE_ENV
;
Try

noUnusedLocals

Report errors on unused local variables.

ts
const 
createKeyboard
= (
modelID
: number) => {
const defaultModelID = 23;
'defaultModelID' is declared but its value is never read.
return {
type
: "keyboard",
modelID
};
};
Try

noUnusedParameters

Report errors on unused parameters in functions.

ts
const 
createDefaultKeyboard
= (modelID: number) => {
'modelID' is declared but its value is never read.
const
defaultModelID
= 23;
return {
type
: "keyboard",
modelID
:
defaultModelID
};
};
Try

Parameters declaration with names starting with an underscore (_) are exempt from the unused parameter checking. e.g.:

ts
const 
createDefaultKeyboard
= (
_modelID
: number) => {
return {
type
: "keyboard" };
};
Try

strict Recommended

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.

strictBindCallApply Recommended

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:

ts

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

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

ts

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

strictBuiltinIteratorReturn Recommended

Built-in iterators are instantiated with a TReturn type of undefined instead of any.

strictFunctionTypes Recommended

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

Here's a basic example with strictFunctionTypes off:

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

With strictFunctionTypes on, the error is correctly detected:

ts
function 
fn
(
x
: string) {
console
.
log
("Hello, " +
x
.
toLowerCase
());
} type
StringOrNumberFunc
= (
ns
: string | number) => void;
// Unsafe assignment is prevented let func:
StringOrNumberFunc
=
fn
;
Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'. Types of parameters 'x' and 'ns' are incompatible. Type 'string | number' is not assignable to type 'string'. 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:

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

strictNullChecks Recommended

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:

ts
declare const 
loggedInUsername
: string;
const
users
= [
{
name
: "Oby",
age
: 12 },
{
name
: "Heera",
age
: 32 },
]; 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.

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

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

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;
};

strictPropertyInitialization Recommended

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

ts
class 
UserAccount
{
name
: string;
accountType
= "user";
email: string;
Property 'email' has no initializer and is not definitely assigned in the constructor.
address
: string | undefined;
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.

useUnknownInCatchVariables Recommended

In TypeScript 4.0, support was added to allow changing the type of the variable in a catch clause from any to unknown. Allowing for code like:

ts
try {
  // ...
} catch (
err
: unknown) {
// We have to verify err is an // error before using it as one. if (
err
instanceof
Error
) {
console
.
log
(
err
.
message
);
} }
Try

This pattern ensures that error handling code becomes more comprehensive because you cannot guarantee that the object being thrown is a Error subclass ahead of time. With the flag useUnknownInCatchVariables enabled, then you do not need the additional syntax (: unknown) nor a linter rule to try enforce this behavior.