Enabling the compiler setting strictNullChecks (which is also included in the strict setting) removes null and undefined from each type and thus requires these to be explicitly declared. TypeScript handbook on Nullable types.
Without strictNullChecks:
declare let implicitlyNullable: number;
implicitlyNullable = 42; //OK
implicitlyNullable = null; //OK
implicitlyNullable = undefined; //OK
Playground Link
With strictNullChecks:
declare let implicitlyNullable: number;
implicitlyNullable = 42; //OK
implicitlyNullable = null; //error
implicitlyNullable = undefined; //error
///////////////////////////////////////
declare let explicitlyNullable: number | null;
explicitlyNullable = 42; //OK
explicitlyNullable = null; //OK
explicitlyNullable = undefined; //error
///////////////////////////////////////
declare let explicitlyUndefinable: number | undefined;
explicitlyUndefinable = 42; //OK
explicitlyUndefinable = null; //error
explicitlyUndefinable = undefined; //OK
///////////////////////////////////////
//nilable = can be both undefined and null
declare let explicitlyNilable: number | undefined | null;
explicitlyNilable = 42; //OK
explicitlyNilable = null; //OK
explicitlyNilable = undefined; //OK
Playground Link
In essence, the compiler option is very similar to automatically applying the NonNullable utility type to every type in existence. So, without strictNullChecks being you don't accept "empty" values is an opt-in.
Speaking for myself, I much prefer the exactness of strictNullChecks. It makes it much easier to write and reason about code without having to sprinkle if(someVar) everywhere because you don't know what somebody would pass in. Even a simple function can be a problem without strict null checks:
function add(a: number, b: number): number {
return a + b;
}
console.log(add(2, 3)); //strictNullChecks: false -> 5
//strictNullChecks: true -> 5
console.log(add(2, null)); //strictNullChecks: false -> 2
//strictNullChecks: true -> compiler error
console.log(add(2, undefined)); //strictNullChecks: false -> NaN
//strictNullChecks: true -> compiler error
Playground Link - strictNullChecks: false
Playground Link - strictNullChecks: true
For convenience, you can create some generic types that handle different types of nullability:
type Nullable<T> = T | null;
type Undefinable<T> = T | undefined;
type Nilable<T> = Nullable<Undefinable<T>>
declare let implicitlyNullable: number;
declare let explicitlyNullable: Nullable<number>;
declare let explicitlyUndefinable: Undefinable<number>;
declare let explicitlyNilable: Nilable<number>;
Playground Link
let test:IMyInterface | null = null;createContext