"Strict Mode" TypeScript config options
Published: 2021-01-25 02:31:02

You can enable the "strict mode" in TypeScript by using the `strict` option. (BTW, TypeScript is the superset of the .. *[the most popular programming language in the world](https://www.google.com/search?q=the+most+popular+programming+language+in+the+world)~*)

For example, here's a sample *tsconfig.json* file where the `strict` option is set to `true`:

```json
{
  "compilerOptions": {
    "target": "es5",
    "lib": [ "esnext" ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "strict": true, // HERE
    "module": "esnext",
    "moduleResolution": "node",
    "isolatedModules": true,
    "noEmit": true
  },
  "include": [
    "src"
  ]
}
```

This article isn't about TypeScript for absolute beginners, this is for intermediate users. However, we are not going to cover all of the configuration options, we're just going to talk about one, the `strict` option.

So what's *strict*?

The `strict` option will subject your code to stricter rules in terms of static type checking. *Stricter* means *safer*, so it's a good thing. The special thing about this `strict` option is that, it's actually a shortcut for a set of seven different options.

The seven options are:
  - `noImplicitAny`
  - `noImplicitThis`
  - `alwaysStrict`
  - `strictBindCallApply`
  - `strictNullChecks`
  - `strictFunctionTypes`
  - `strictPropertyInitialization`

So yeah, I lied. We're not just going to talk about *one* configuration option, we're going to talk about *seven of them!!!*

Before we begin, replace this in the config:

```js
  "strict": true,
```

with these guys:

```js
  "noImplicitAny": true,
  "noImplicitThis": true,
  "alwaysStrict": true,
  "strictBindCallApply": true,
  "strictNullChecks": true,
  "strictFunctionTypes": true,
  "strictPropertyInitialization": true,
```

We are doing it this way so that you can easily toggle each individual one on and off to see its effect.

Now let's begin!

## 1. noImplicitAny

It makes sure that you can't just use "JavaScript," it forces you to use "TypeScript."

So you can't just do this:

```ts
function double(x){
  return x + x
}
```

`tsc` or VS Code will give you an error.

`x` will be typed `any`, and it's implicit (implicit means you didn't assign it yourself), that goes against the `noImplicitAny` rule.

To fix this, you should give it a type, `any` is fine too:

```ts
function double(x: any){
  return x + x
}
```

Since now it's explicit, not implicit. 

If you're fine with implicit `any`, you can just set this option to `false`.

## 2. noImplicitThis

With this option, you can't use `this` directly like this inside a function:

```ts
function print(x){
  console.log(this, x)
}
```

So what's wrong with this?

`this` is typed `any` implicitly. 

So to fix this problem, we have to make `this` the first argument:

```ts
function print(this, x){
  console.log(this, x)
}
```

Don't worry, you can still use the function normally like this:

```ts
print('Hello')
```

No need to pass in the `this` reference yourself.

## 3. alwaysStrict

You know how ES5 allows you to write code in a *strict mode* by placing a string on top of a file:

```js
"use strict";
```

Turning on this option will make every compiled `.js` file to have this as the first line.

## 4. strictBindCallApply

Let's say you have a function like this:

```ts
function foo(a: number, b: string) {
  console.log(a + b);
}
```

Calling the function like this will give you an error:

```ts
foo(1, 2) // error
```

Because the second variable has to be a string.

But if you're setting the `strictBindCallApply` option to `false`, you can call the function like this without error:

```ts
foo.apply(undefined, [ 1, 2 ])
```

This is a *loophole*, and this loophole can make your code buggy. The `strictBindCallApply` option is used for fixing this loophole.

By setting `strictBindCallApply` to `true`, you get the helpful type checking error again:

```ts
foo.apply(undefined, [ 1, 2 ]) // error
```

## 5. strictNullChecks

This option makes sure that you can't assign `null` or `undefined` to a variable of an existing type:

```ts
let num = 1;
num = null; // error
```

So in the above code, the variable is inferred to be a `number` type, so you can't reassign it with `null`.

## 6. strictFunctionTypes

This one is a bit elaborate, I'll have another article talking about this specifically. But in short, it's about making the function types *contravariant* instead of the default *bivariant* behavior.

## 7. strictPropertyInitialization

This is an option for creating a `class`. Declared members of a class need to be assigned with values, either in the constructor or directly in the declaration.

```ts
class Foo {

  bar: string
  bar2: number // error

  constructor(){
    this.bar = 'Hello'
  }
}
```

`bar` doesn't raise an error because it's been initialized with `'hello'` in the constructor, but `bar2` isn't initialized.

## Bottom Line

*Strict TypeScript* is good, and it makes sense. If you want a simpler life, just set the `strict` option to `true` and fix the any type error raised by VS Code.