Advanced Types
In this section we will discuss some advanced concepts and techniques that would helps to improve your TypeScript code.
Type Guard
TypeScript is aware of your if
check and able to narrow down the type. Consider the following example:
const findEvenNumberAndDivideIt = (numbers: number[]): number => {
const evenNumber = numbers.find((num) => num % 2 === 0);
return evenNumber / 2; // Hey, this could be undefined!
};
The type error of TypeScript is valid. We can fix it by doing a null check:
const findEvenNumberAndDivideIt = (numbers: number[]): number => {
const evenNumber = numbers.find((num) => num % 2 === 0);
if (evenNumber) {
return evenNumber / 2;
}
return 0;
};
TypeScript is smart enough to know that once you do a null check, the value will no longer be undefined
.
Custom Type Guard
Many times you want to abstract away common type check, like isDefined
function:
const isDefined = (value: any) => typeof value !== 'undefined';
Now if we apply to the findEvenNumberAndDivideIt
example:
const isDefined = (value: any) => typeof value !== 'undefined';
const findEvenNumberAndDivideIt = (numbers: number[]): number => {
const evenNumber = numbers.find((num) => num % 2 === 0);
if (isDefined(evenNumber)) {
// This could be undefined??? 🤦♂️🤦♂️
return evenNumber / 2;
}
return 0;
};
This is because TypeScript will not go into the implementation of isDefined
to figure our the implementation. For TypeScript it is just a function that returns a boolean value.
We can restore the previous typechecking ability by making the isDefined
function as custom type guard:
const isDefined = <T,>(value: T | undefined): value is T => typeof value !== 'undefined';
const findEvenNumberAndDivideIt = (numbers: number[]): number => {
const evenNumber = numbers.find((num) => num % 2 === 0);
if (isDefined(evenNumber)) {
// Oh my lord TypeScript is happy again 🙏🙏
return evenNumber / 2;
}
return 0;
};
Do It: Creating Type Guard
Refactor all the functions in typecheck.ts
so that they becomes typeguard.
Type Utilities
Omit
<Form />
<Input />
Pick
- Opposite of
Omit
type ThirdPartyProps = {
color: 'default' | 'success' | 'danger' | 'info' | 'warning';
size?: 'large' | 'small';
children: string;
};
type MyProps = Pick<ThirdPartyProps, 'color' | 'size'>;