타입스크립트가 코드를 파악해서 타입을 추론하는 것을 제어 흐름 분석이라 부른다.
// 간단한 null과 undefined 구분
function strOrNullOrUndefined(param: string | null | undefined) {
if (param === undefined) { // 또는 typeof param === 'undefined'
param; // undefined
} else if (param === null) {
param; // null
} else {
param; // string
}
}
// Array 구분
function strOrNumArr(param: string | number[]) {
if (Array.isArray(param)) {
param; // number[]
} else {
param; // string
}
}
// instanceof 연산자 활용 (클래스, 함수)
class A {}
class B {}
function classAorB (param: A | B) {
if (param instanceof A) {
param; // A
} else {
param; // B
}
}
interface X {
width: number;
height: number
}
interface Y {
length: number;
center: number;
}
// X, Y는 타입스크립트의 인터페이스이므로 에러가 발생
function objXorY(param: X | Y) {
if (param instanceof X) {
param; // error
} else {
param;
}
}
function objXorY(param: X | Y) {
// 자바스크립트에서 유효한 방식이지만, width 속성이 Y에 존재하지 않지만 width 속성에 접근해서 에러 발생
if (param.width) { // error
param;
} else {
param;
}
}
// 👍
function objXorY(param: X | Y) {
if ('width' in param) {
param; // X
} else {
param; // Y
}
}
interface Money {
_type: 'money';
amount: number;
unit: string;
}
interface Liter {
_type: 'liter';
amount: number;
unit: string;
}
function moneyOrLiter(param: Money | Liter) {
if (param._type === 'money') {
param; // Money
} else {
param; // Liter
}
}
직접 타입 좁히기 함수 만들어서 사용 (타입 가드)
function isMoney(param: Money | Liter) {
if (param._type === 'money') {
return true
} else {
return false
}
}
function moneyOrLiter(param: Money | Liter) {
if (isMoney(param)){
param; // Money | Liter
} else {
param; // Money | Liter
}
}
function isMoney(param: Money | Liter): param is Money {
if (param._type === 'money') {
return true
} else {
return false
}
}