[TypeScript] Narrowing 할 수 있는 방법 ( typeof, in연산자, instanceof )

2022. 12. 30. 13:29TypeScript

⚡️Narrowing 하는 방법

1. undefined 타입일 경우 처리하는 방법

2. 복잡한 object자료들 narrowing 하는 방법

 

null & undefined 체크하는 법

실제로 개발할 때 어떤 변수나 함수파라미터에 null, undefined가 들어올 경우 

어떻게 대처할지 if문으로 코드짜는 경우가 매우 많을 겁니다. 

if (저 변수가 undefined일 경우){ }

1. && 스킬을 쓰면 저런 if문을 생략할 수 있습니다. 

2. && 연산자의 다른 기능

   ⓵ 원래 && 이건 조건식 2개가 참이면 전부 참으로 판정해주세요~ 라는 논리연산자이다

   ⓶ && 기호로 비교할 때 true와 false를 넣는게 아니라 자료형을 넣으면 && 사이에서 처음 등장하는 falsy 값을 찾아주고 그게 아니면            마지막 값을 남겨줍니다.

       ( falsy 값은 false와 유사한 기능을 하는 null, undefined, NaN 이런 값들을 의미합니다. ) 

1 && null && 3   // null이 남음
undefined && '안녕' && 100  // undefined 남음

⚡️typeof 연산자 

if (변수 && typeof strs === "string") {} 

이렇게 사용하면 변수가 undefined라면 undefined가 남아서 if문이 실행되지 않고,

(if문 조건식안에 falsy 값이 남으면 if문 실행되지 않습니다)

변수가 string 타입이면 if문이 실행됩니다.

변수가 null, undefined인 경우를 쉽게 거를 수 있는 문법이라고 보면 되겠습니다. 

function printAll(strs: string | undefined) {
  if (strs && typeof strs === "string") {  
    console.log(s);
  } 
}

참고) if (변수 != null) 이렇게 조건식을 써도 null, undefined 이거 두 개를 동시에 거를 수 있습니다. 


⚡️in 연산자로 object 자료 narrowing

이런 if문을 써도 narrowing이 가능하다는 뜻입니다.

if (키값 in object자료형) 이렇게 쓰면 됩니다.

type Fish = { swim: string };
type Bird = { fly: string };
function 함수(animal: Fish | Bird) {
  if ("swim" in animal) {
    return animal.swim
  }
  return animal.fly
} 

1. swim이라는 속성이 animal이라는 변수에 들어으면 실행시켜라 라는 뜻입니다.

2. 서로 배타적인 속성을 가져와야 narrowing이 가능합니다.


⚡️class로부터 생산된 object라면 instanceof로 narrowing

object 에 instanceof 키워드를 붙여서 부모 클래스가 누군지 검사할 수 있는데

이것도 narrowing 역할을 할 수 있습니다.

 

가장 쉽게 new 키워드로 object 생산할 수 있는게 바로 날짜인데

자바스크립트에선 new Date() 이렇게 하면 date object 라는게 생성됩니다. 

그래서 instanceof로 부모 클래스가 누군지 검사할 수 있습니다. 

let 날짜 = new Date();
if (날짜 instanceof Date){
  console.log('참이에요')
}

⚡️literal type이 있으면 narrowing 쉬움 

type Car = {
  wheel : '4개',
  color : string
}
type Bike = {
  wheel : '2개',
  color : string
}

function 함수(x : Car | Bike){
  if (x가 Car타입이면요){
    console.log('이 차는 ' + x.color)
  } else {
    console.log('이 바이크는 ' + x.color)
  }
}

1.  Car, Bike 타입을 각각 만들었는데 object 자료가 들어올 수 있습니다.

2. 함수에 Car 타입을 입력할 경우 실행시키는 방법

   ⓵ typeof 연산자를 써도 그냥 object 입니다~ 라고만 나옵니다.

       ( 왜냐면 typeof 연산자는 string, number, object 이런 것만 구분해주기 때문입니다. )

   ⓶ in 연산자를 써도 Car, Bike 둘 다 배타적인 속성이 없어 narrowing하기엔 힘들어보입니다. 

 

object들 구분할 일이 많을 때 literal type을 만들어두면 편리한데 

1. 서로 비슷한 object들이 들어와도 literal type으로 narrowing 가능하기 때문입니다. 

2. object 마다 literal type으로 wheel이 있습니다.

3. Car 타입은 무조건 wheel 출력해보면 4

4. Bike 타입은 wheel 출력해보면 무조건 2가 나옵니다.

    ( 이거 가지고 object 끼리 narrowing 가능합니다. )

5. if문으로 "지금 이 변수가 wheel 속성에 저장된게 4냐" 라고 물어보면 이건 누가봐도 Car 타입아니겠습니까.

type Car = {
  wheel : '4개',
  color : string
}
type Bike = {
  wheel : '2개',
  color : string
}

function 함수(x : Car | Bike){
  if (x.wheel === '4개'){
    console.log('the car is ' + x.color)
  } else {
    console.log('the bike is ' + x.color)
  }
}