# TypeScript Strict Mode

The `"strict": true` option in `tsconfig.json` is a "meta-flag" that enables a wide range of type-checking behavior that results in stronger guarantees about program correctness. Enabling strict mode is highly recommended for all new projects.

When you enable `strict`, you automatically enable all of the following flags. You can also toggle them individually if you need a more granular migration path.

## 1. `noImplicitAny`

This flag raises an error on expressions and declarations with an implied `any` type.

*   **Without strict:** TypeScript falls back to `any` if it can't infer a type.
*   **With strict:** You must explicitly annotate the type.

```typescript
// Error: Parameter 's' implicitly has an 'any' type.
function fn(s) {
  console.log(s.substr(3));
}
```

## 2. `strictNullChecks`

This is arguably the most important flag.

*   **Without strict:** `null` and `undefined` are valid values for *every* type (e.g., a `number` variable can hold `null`).
*   **With strict:** `null` and `undefined` are distinct types. If a variable can be null, you must declare it as a union type (e.g., `string | null`).

```typescript
let name: string = "Alice";
// Error: Type 'null' is not assignable to type 'string'.
// name = null; 

let maybeName: string | null = "Bob";
maybeName = null; // OK

// You must check for null before using methods
// maybeName.toUpperCase(); // Error: Object is possibly 'null'.
if (maybeName) {
    maybeName.toUpperCase(); // OK
}
```

## 3. `strictPropertyInitialization`

Ensures that class properties are initialized in the constructor or by a property initializer.

```typescript
class User {
  name: string; // Error: Property 'name' has no initializer and is not definitely assigned in the constructor.
  age: number;  // Error

  constructor() {
    // We forgot to set this.name and this.age
  }
}
```

**Fix:** Initialize them, make them optional (`name?: string`), or use the definite assignment assertion (`name!: string`) if initialized indirectly.

## 4. `strictFunctionTypes`

Enforces stricter checking for function types, specifically regarding parameter bivariance. It ensures that function arguments are contravariant (you can't pass a function that expects a specific subtype to a place that expects a base type).

```typescript
function fn(x: string) {
  console.log("Hello, " + x.toLowerCase());
}

type StringOrNumberFunc = (ns: string | number) => void;

// Error: Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'.
// Types of parameters 'x' and 'ns' are incompatible.
let func: StringOrNumberFunc = fn;
```

## 5. `noImplicitThis`

Raises an error when `this` has the type `any`. This usually happens when using `this` inside a standalone function that isn't a method of a class.

```typescript
function logId() {
    // Error: 'this' implicitly has type 'any' because it does not have a type annotation.
    console.log(this.id);
}
```

## 6. `strictBindCallApply`

Ensures that the built-in methods `bind`, `call`, and `apply` are invoked with the correct argument types for the underlying function.

```typescript
function add(a: number, b: number) {
    return a + b;
}

// Error: Argument of type '"hello"' is not assignable to parameter of type 'number'.
add.call(undefined, 1, "hello");
```

## 7. `useUnknownInCatchVariables`

Changes the default type of a variable in a `catch` clause from `any` to `unknown`. This forces you to check the type of the error before using it.

```typescript
try {
    // ...
} catch (err) {
    // Error: Object is of type 'unknown'.
    // console.log(err.message);

    if (err instanceof Error) {
        console.log(err.message); // OK
    }
}
```

## 8. `alwaysStrict`

Ensures that your files are parsed in ECMAScript strict mode, and emits `"use strict"` at the top of each source file.

[[programming/javascript/typescript/typescript]]
[[programming/javascript/typescript/tsconfig]]