[TIL] TypeScript 타입확정하기 <Narrowing>

동화·2023년 3월 29일
0

TIL

목록 보기
15/21
post-thumbnail
post-custom-banner
function 함수(x :number | string){
   return x + 1
}

이렇게 함수를 지정해주면 에러가 난다.

타입스크립트는 여러 개의 타입을 이용할 때
타입을 확정지어주지 않으면 까다로운 타입스크립트는 오류를 내기 때문에,
narrowing을 꼭 해주어야 한다.

이럴 때 해결하는 방법이 narrowing이나 assertion을 이용하는 건데,
assertion에 대한 내용은 저번 숙제 게시글에 있으니
기본적은 narrowing이나 정리해보도록 하장

If 문

function 함수(x: number | string){
    if (typeof x === 'string'){
        return x + '1';
    } else {
        return x + 1;
    }
}

제일 직관적이고 쉬운 방법이당

else {} 이거 없으면 에러가 난다.
너 이거는 return 없어~ 하고 오류 날까봐 알려주는 건데,
tsconfig.js 에서 "noImplicitReturns": false, 이걸 넣어주면 오류가 안난다.
그래도 엄격하게 쓰는 게 좋으니 else를 빼먹지 말ㄹ도록 하자




in 연산자

in 연산자로 object 자료 narrowing하는 방법

object에서 서로 다른 유니크한 속성들을 가지고 있다면

if (이 파라미터가 a라는 속성을 안에 가지고 있냐) 이런 if문을 써도 narrowing이 가능하다.

if (키값 in object자료형) 이렇게 써주면 됨.

type Fish = { swim: string };
type Bird = { fly: string };

이럴 때 typeof 를 쓸 수가 없다.
typeof 는 말그대로 string, number, boolean 같은 타입만 가져올 수 있기 때문에,
두 다른 속성을 가진 오브젝트를 비교할 수가 없음.

function 함수(animal: Fish | Bird){
  if ('swim' in animal) {
    return animal.swim
  }
  return animal.fly
}

그럴 때 위처럼 in을 쓸 수가 있다.
서로 배타적인 속성을 지닐 때 사용가능하다.




Discriminated Union

정해진 literal type

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

type Transport = Car | Bike

타입 Car, Bike는 둘 다 wheel라는 동일한 키를 갖지만 키의 값은 각 '4개', '2개'로 다른 값을 갖는다.

function isCar(x : Transport){
  if (x.wheel === '4개'){
    console.log('the car is ' + x.color)
  } else {
    console.log('the bike is ' + x.color)
  }
}

함수 isCar 인자는 Transport 타입을 갖는다.

  • 인자로 들어온 값의 키인 wheel 값이 4개인 경우, 인자로 Car가 들어온 것이므로 x자리에 Car의 color값을 한다
  • 인자로 들어온 값의 키인 wheel 값이 2개인 경우, 인자로 Bike가 들어온 것이므로 Bike의 color 값을 출력한다.



?

interface Shape {
  kind: "circle" | "square";
  radius?: number;
  sideLength?: number;
}

이런 interface가 있다 칠 때,
도형의 종류가 원일지, 사각형일지 모르므로 radius나 sideLength의 값을 ? 로 두었다.

function getArea(shape: Shape) {
  return Math.PI * shape.radius ** 2;
}

만약 면적을 구하는 함수를 이렇게 나타낸다면 당연히 오류가 난다
왜냐면 radius가 있는지 없는지도 모르는데 다짜고짜 쓰라고 하니 예민킹 타입스크립트는 안된다고 말하는 거다


function getArea(shape: Shape) {
  if (shape.kind === "circle") {
    return Math.PI * shape.radius ** 2;
  }
}

그렇다고 if를 사용해서 얘 kind는 원이야! 라고 한다 해봤자 안된다
어차피 radius 모르기는 마찬가지니깐..


function getArea(shape: Shape) {
  if (shape.kind === "circle") {
    return Math.PI * shape.radius! ** 2;
  }
}

radius는 있어! 있다구! 하고 말해놓으면 오류신세는 면할 수 있다
하지만.. radius를 안 써버리면.. 또 오류가 날 것이야



이때 타입 지정방식 자체를 바꾸어 주면 된다.

interface Circle {
  kind: "circle";
  radius: number;
}
 
interface Square {
  kind: "square";
  sideLength: number;
}
 
type Shape = Circle | Square;

이렇게 되면 Shape 라는 타입은 공통적으로 kind 라는 속성을 가지고, 각각 고유의 필수적인 속성도 가지게 되는 것이다.

function getArea(shape: Shape) {
  return Math.PI * shape.radius ** 2;
}

이러면 보다 정확한 오류를 알려주게 된다.
이때 if문을 사용해주면 오류없이 ts가 타입을 잘 감지하게 된다.

이렇게 코드를 더 직관적으로 작성할 수 있고,
공통적인 property를 갖게 만들어 구분이 쉽도록 한다.




instanceof

x instanceof Foo 는 Foo 라는 프로토타입체인 안에 x라는 인스턴스가 있나 확인하는 것이다.

function logValue(x: Date | string) {
  if (x instanceof Date) {
    console.log(x.toUTCString());
  } else {
    console.log(x.toUpperCase());
  }
}




null & undefined 체크하기

if (저 변수가 undefined일 경우) 이렇게 해줘~

살다보면 이런 경우를 많이 맞이하게 된다.
이런 상황을 방어해 안전하게 하고 넘어가는게 좋기 때문이다.

function 함수(a : string | undefined){
  if (typeof a === 'string') {
  	} else {
  	}
}

당연히 이렇게 쓰면 된다.
그런데 이 코드를 한 줄로 줄일 수가 있음

function 함수(a : string | undefined){
	if (a && typeof a === 'string') { ...

그러니까,

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

이렇게 사용하면 변수가 undefined라면 undefined가 남아서 if문이 실행되지 않고,
(if문 조건식안에 falsy 값이 남으면 if문 실행XXX)
변수가 string 타입이면 if문이 실행된다.

즉 null, undefined를 쉽게 거를 수가 있는 것이다.


&&

원래 && 이건 조건식 2개가 참이면 전부 참으로 판정해주세요~ 라는 논리연산자인데 여러 개를 사용하면 이상한 현상이 있다.

  • && 기호로 비교할 때 true와 false를 넣는게 아니라 자료형을 넣으면,
    && 사이에서 처음 등장하는 falsy 값을 찾아주고, 그게 아니면 마지막 값을 남겨줌
  • falsy 값은 false와 유사한 기능을 하는 null, undefined, NaN 이런 값들을 의미
1 && null && 3   // null이 남음
undefined && '안녕' && 100  // undefined 남음




👍🏻 참고

post-custom-banner

6개의 댓글

comment-user-thumbnail
2023년 3월 29일

타입스크립트 계속 정리해주세요 ..!!

답글 달기
comment-user-thumbnail
2023년 4월 2일

예민킹 타입스크립트... 정말 맞는 말입니다 🤣

답글 달기
comment-user-thumbnail
2023년 4월 2일

in 연산자는 처음보는데 공부하고 갑니다!

답글 달기
comment-user-thumbnail
2023년 4월 2일

개빡칩니다.. 맨날 null 오류 뜨면 || null이나 "" 쓰는 거 습관돼서 맨날 씁니다 저는 ㅋㅋㅋㅋ 잘봤습니다

답글 달기
comment-user-thumbnail
2023년 4월 2일

정리 넘나 깔끔하네요!

답글 달기
comment-user-thumbnail
2023년 4월 3일

복습 잘하고 갑니다 ! 설명이랑 예시 넘 깔끔해요 !

답글 달기