In the previous article, we learned about some of the typescript best practices. let's see more about them.
Optional Chainingβ
Optional Chaining ?.
is a new feature in TypeScript 3.7. It allows you to access properties of an object without having to check for undefined
first.
If no property is found, will cause an error.
Uncaught TypeError: Cannot read property...
With the optional chaining, the code above becomes:
Nullish coalescing Operatorβ
Nullish coalescing operator ??
is a new feature in TypeScript 3.7. It allows you to access properties of an object without having to check for null
or undefined
first.
For example:
const User = {
age: 0,
};
const age = User?.age ?? 0; // age = 0
const age = User?.age || "default"; // age = 'default'
Constant enumerationβ
Constant enumerations are enumerations defined using const enum:
const enum Direction {
Up,
Down,
Left,
Right,
}
let direction = [Direction.Up, Direction.Down, Direction.Left, Direction.Right];
Constant enumeration differ from normal enumeration in that they are removed at compile time and cannot contain computed member
The compiler result is:
var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
Type mapping (in)β
The function of the in
keyword is mainly to do type mapping, traversing the key
of the existing interface or traversing the union type. Take the built-in generic interface Readonly
, which is implemented as follows:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
It makes all attributes of the interface read-only:
interface Obj {
a: number;
b: string;
}
type ReadonlyObj = Readonly<Obj>;
// equals to
interface ReadonlyObj {
readonly a: number;
readonly b: string;
}
Conditional typesβ
The syntax of conditional types is the same as that of ternary expressions, and is often used in cases where the type is uncertain:
T extends U ? X : Y;
So what that means is, if T is a subset of U, it's type X, otherwise it's type Y. Take the built-in generic interface Extract, which is implemented as follows:
type Extract<T, U> = T extends U ? T : never;
- TypeScript uses the
never
type to indicate states that should not exist. If the type in T exists in U, return, otherwise discard. - Suppose we have two classes with three public attributes that can be extracted from
Extract
:
interface A {
a: string;
b: number;
c: boolean;
}
interface B {
a: string;
b: number;
d: boolean;
}
type CommonKeys = Extract<keyof A, keyof B>; // 'a' | 'b'