[ Typescript ] - 타입추론 & 타입 확정시켜버리는 Narrowing 과 Assertion

최문길·2023년 12월 21일
1

Typescript

목록 보기
6/23

타입 추론( Type Inference )

타입 추론은 컴파일러가 코드를 분석하여 변수나 매개변수의 타입을 자동으로 추론해 주는 방식이다.

  • tsc 명령어를 통해 tsconfig 에서 설정된 방식으로 에디터가 컴파일을 시작한다.

타입 추론에 의해 좁혀진 타입을 활용하여 코드를 작성할 수 있다.

타입 추론은 narrowing 의 일종인 이유는 타입 추론 과정에서 컴파일러가 가능한 한 세부적인 타입으로 추론하려고 하기 때문이다.

이러한 추론 과정에서 컴파일러는 다양한 방법으로 narrowing을 수행한다.

Type Narrowing

Narrowing은 좁히다라는 의미로

typescript에서 특정 타입 으로 제한하는 작업이다.

const 함수 = (x:number|string):number =>x+1

Operator '+' cannot be applied to types 'string | number' and 'number'

string | number 와 number에는 연산기호 + 를 사용 할 수 없다라고 에러문구를 친절히 띄워주는데

타입지정을 확실히 해달라는 이야기 이다.

이럴때 쓸 수 있는 방법 이 있는데,

if문 등으로 타입을 하나로 정해(좁혀=narrowing)주면 된다.

그래서

const 함수 = ( x : number | string ) :number => {
      if (typeof x === 'number') {
            return x + 1
          } 
       else if (typeof x === 'string') { // string으로 들어올때도 ...
            return 1
       }
        else {
            return 0
        }
}
  • typeof 를 사용하여 타입을 좁혀주고 (= narrowing)

  • 들어올 수 있는 인자값은 string || number 이고 return 값은 number 만 허영 되므로

  • string이 들어올 때의 조건문을 사용하여 x 값이 string 이면 어떻게 할 지 처리를 해줘야 한다.

  • else를 써서 타입이 any 로 추론될 가능성이 있기 때문에 이를 방지하기 위해서 항상 else블록을 추가해야 한다.

Type Assertion

narrowing으로 조건문을 이용하여 하는것이 마음에 걸린다면

타입을 간편하게 assertion 할 수도 있다.

" 이 변수의 타입을 number로 생각해주쇼 "
이런 뜻으로 코드를 짜면 컴파일러가 ok 해주는데

변수명 as string

이런 식으로 as keyword 를 쓰면 된다.

const 함수 =  (x : number | string ):number (x as number) + 1

위의 식은

함수에 x 값이 number | string이 들어올건데 return 하는 타입은 number 이고 return 하는 x는 number로 덮어씌우고 거기에 + 1 해주세요 라는
의미이다.

간단하게 말해서

나는 이 변수를 number라고 주장하렵니다. 라는 뜻이며 실제로 그렇게 타입을 변경해준다.

근데 이렇게 타입을 내가 지정해버리는거라면

내가 짠 코드에서 '함수에 무조건 숫자가 들어올 거임' 이라는 사실을 알고 있어야 안전하게 쓸 수 있을 듯 하다.

as keyword의 특징

  1. as keyword는 union type 같은 복잡한( 여러 경우의 수를 가진) 타입을 하나의 정확한 타입으로 줄이는 역할을 수행한다.
let anyStr : any = 'kim'
anyStr  as number

let str : string = 'kim'
str as number

any는 눈감아 주지만,

string으로 타입지정한 str은 눈감아 주지 않고
" 혹시 너 실수한거 아니야?" 이런 문구를 띄워준다.

  1. 타입을 임시 해제용이다. 실제 코드 실행결과는 as 있을 때나 없을 때나 거의 동일하다.
const 함수 = (x : string | number ): number=> (x as number) + 1

이 함수에 '123' 을 값을 넘겨주면 어떻게 될까??

함수('123') // '1231' 

as는 그냥 타입만 눈감아주는거임...

as의 사용처는

  1. 왜 타입에러가 나는지 정말 모르겠으나 상황에 임시로 에러해결용으로 사용
  2. 내가 어떤 타입이 들어올지 senior 개발자가 물어봐도 정말 확실하게 알고 있는데, 컴파일러 에러가 방해할 때

assertion의 옛날 문법

// as 키워드 대신 <> 괄호로 했다. 

let name :number= 123

name as string //현재
<string>name // 옜날

as 의 유용함은

type Person = {
    name : string
}
function 변환기<T>(data: string): T {
    return JSON.parse(data) as T;
}
const jake = 변환기<Person>('{"name":"kim"}');

이럴때 발휘 된다.

정리

  • union타입과 같이 타입이 2개이상이고 하나로 정해주는 방법이 narrowing

  • narrowing을 할 때 if문을 사용할 경우 else 구문을 반드시 명시 해줘야한다.

  • assertion은 단지 타입을 임시용으로 확정해주는 용도

  • assertion은 남용하지 말자.

0개의 댓글