본문으로 건너뛰기

Type Guards

You are capable of writing safe code with type guard in typescript.

Type guard​

function repeatThree(value: number | string) {
// type narrowing is required.
if (typeof value === "string") {
return value.repeat(3) // error occurs since number doesn't have repeat() method.
}

return value * 3
}

console.log(repeatThree('hi')); // hihihi
console.log(repeatThree(3)); // 9

Truthiness guards​

function printIfTruthNum(value: string | number | undefined | null) {
if (typeof value === "number") {
// console.log(`number: ${value}`)
logger.warn(`number:${value}`);
} else if (!value) {
console.error('this is falsy')
} else {
console.log(value)
}
}

printIfTruthNum(0); // number: 0
printIfTruthNum(null); // this is falsy
printIfTruthNum('champ'); // champ
정보

Take care of that number 0 is also Falsy value

In operator​

in operator is type narrowing checking property existence in object.

interface Movie {
title: string;
duration: number;
}

interface TVShow {
title: string;
numOfEpisodes: number;
episodesDuration: number;
}

function getRuntime(media: Movie | TVShow) : number {
// media is type narrowed to `TVShow`
if ('episodesDuration' in media) {
return media.numOfEpisodes * media.episodesDuration;
} else{
// media is type narrowed to `Movie`
return media.duration;
}
}

const movie1 = {title: 'Khazix', duration: 140}
const tvShow1 = {title: 'Vladimir', numOfEpisodes: 20, episodesDuration: 10}
console.log(getRuntime(movie1)); // 140
console.log(getRuntime(tvShow1)) // 200 (20 * 10)

instanceof​

instanceof is a javascript operator that allow us to check if an instance of another prototype(class)

interface IUser {
name: string;
}

// https://timmousk.com/blog/typescript-instanceof-interface/

class RiotUser implements IUser {
constructor(public readonly name: string, readonly riotId: string = "RID: " + name) {
}
}

class NexonUser implements IUser {
constructor(public readonly name: string, readonly nexonId: string = "NID: " + name) {
}
}

const riotUser = new RiotUser('riot1');
const nexonUser = new NexonUser('nexon1');

function printUserName(user: IUser) {

if (user instanceof RiotUser) {
console.log(user.name); // riot1
console.log(user.riotId); // RID: riot1
}

if (user instanceof NexonUser) {
console.log(user.name); // nexon1
console.log(user.nexonId); // NID: nexon1
}
}

printUserName(riotUser); //
printUserName(nexonUser);
정보

Don't use this when checking interface.
instanceof type narrowing is only allowed to prototype (class).

function printUserName(user: IUser) {
// 🚫 using instanceof to interface is not allowed since interface is just type.
// if (user instanceof IUser) {
//
// }
}

Above code must lead to error.

Pros and Cons​

Using instanceof have trade-off.
It might be a sign that your class hierarchy could be refactored to be more cohesive and have fewer dependencies on external state.

Pros​

Reduce code duplication

Cons​

Difficult to modify the implementation of each class.
instanceof code could break Open-Closed-Principal (OCP) because additional class added, that code should be modified.

When to use​

팁

Use instanceof All classes are independent on external state and methods are implemented in a similar way across all classes.
Don't use when modification is important.