[TS] About TypeScript #3

hangkemiii·2022년 6월 23일
0

Typescript

목록 보기
3/3
post-thumbnail

Narrowing & Assertion

function foo(x: number | string) {
  return x + 1
}

위와 같은 함수의 파라미터에 Union types로 두 가지의 type을 정의하면, 에러가 발생하게 된다. 이는 Union Type에는 TypeScript에서 일반적으로 조작을 못하게 막아놓기 때문인데, 이런 에러가 발생하면 타입을 하나로 Narrowing 해주거나 Assertion을 해주어야 한다.

Type Narrowing

function foo(x :number | string){
  if (typeof x === 'number') {
    return x + 1
  } 
  else if (typeof x === 'string') {
    return x + 1
  }
  else {
    return 0
  }
}

Type Narrowing이란, if 문 등으로 타입을 하나로 정해주는 것을 뜻한다. 위 코드에서는 if문과 typeof 키워드로 현재 파라미터의 타입을 검사해서 타입별로의 상황을 설정해 두었다. 이렇듯 typeof와 같은 명령어로 추가적인 타입 체크나 할당을 이용하여 변수의 타입을 작은 범위로 좁혀 나가는 것을 Type Narrowing이라고 한다.

Type Assertion

Assertion 역시 타입스크립트가 추론하지 못하는 타입을 as 키워드를 통해 명시해주는 방법이다.

변수명 as string

과 같은 형태의 문법으로 사용하게 되는데, 이 코드는 '이 변수의 타입을 string으로 추론하라'라고 타입스크립트 컴파일러에게 입력하게 된다.


function foo(x: number | string) {
  return (x as number) + 1
}

하지만 as 키워드를 사용할시에는 두 가지의 특징이 있다.

  1. as 키워드는 union type 같은 복잡한 타입을 하나의 정확한 타입으로 줄이는 역할을 수행한다. (number type을 as string으로 바꾸려면 에러가 발생한다.)

  2. 실제 코드 실행결과는 as 키워드가 있을때와 없을때가 거의 동일하다.

그렇기 때문에 as 문법은 타입에러가 발생했을시에 타입 에러의 이유를 모를떄 디버깅용으로 사용하거나, 개발자가 어떤 타입이 들어올지 확실하게 알고 있는데 컴파일러 에러가 발생할 때와 같은 상황에서만 사용하고 평소에는 Type Narrowing을 사용하는 편이 좋다.


Type Aliases

타입스크립트에서 타입을 정의하다보면 타입이 너무 길고 복잡하게 나열되는 경우가 있다. 또한, 반복되는 타입들의 재사용이 필요한 경우도 있는데, 이럴때는 타입을 변수에 담는 것처럼 type이라는 키워드로 담아서 사용하면 된다. 이를 Type Alias(타입 별칭)라고 한다.

type Animal = string | number | undefined;
let animals :Animal;

타입을 변수처럼 만들어서 쓰는 alias 문법은 관습적으로 대문자로 시작한다. 또한 Object에 타입 지정할때에도 자주 활용할 수 있다.

type person = {
  name: string,
  age: number,
}

let teacher :person = { name: 'Kyeom', age: 26 }

readonly로 잠그기

type Girl = {
  readonly name: string,
}

let girlFriend :Girl = {
  name : '엠버'
}

girlFriend.name = '유라' 

readonly 키워드는 속성 왼쪽에 붙일 수 있으며 특정 속성을 변경 불가능하게 잠굴 수 있다. const는 재할당만 금지되어 있고, object의 속성을 변경하는 것까지 관여하지 않기 때문에 이를 방지하고 싶으면 readonly 키워드를 사용하는 것이 좋다.

속성 몇개가 선택사항일때

type Square = {
  color? : string,
  width : number,
}

let Square2 :Square = { 
  width : 100 
}

만일 특정 Object에서 color, width 속성 중 color 속성이 선택사항이라면, Type alias를 여러개 만들어야 하는 것이 아니라 물음표 연산자를 사용하면 된다. 물음표 연산자는 해당 type이 아니라 undefined type도 가질 수 있음을 의미한다.

Type 키워드 병합

type Name = string;
type Age = number;
type NewOne = Name | Age;

Type 키워드 역시 | 연산자를 사용하여 Union Type을 만들 수 있다.

object에 지정한 타입의 경우 역시 병합이 가능한데, & 연산자를 사용하면 object 안의 두 개의 속성을 extends 해주게 된다. 물론 Type alias & Type alias 말고도 Type alias & { name : string } 와 같이도 작성이 가능하다.

type PositionX = { x: number };
type PositionY = { y: number };
type XandY = PositionX & PositionY
let coordinate :XandY = { x : 1, y : 2 }

Literal Type

let john :'대머리';
let kim :'솔로';

Literal Type이란, 특정 글자나 숫자만 가질 수 있게 제한을 두는 타입을 뜻한다.

let direction: 'left' | 'right';
direction= 'left';

function foo(a : 'hello') : 1 | 0 | -1 {
  return 1 
}

literal type에서도 union type이 사용 가능한데, 위 코드와 같은 경우에는 direction의 값으로 'left'와 'right'만 가질 수 있다. 함수 역시 파라미터와 return 값으로 Literal type을 설정할 수 있다.

as const


let something = {
  name : 'kim'
}

function foo(a : 'kim') {

}
foo(something.name)

위와 같은 코드를 입력하게 되면, 다음과 같은 에러가 발생하게 된다.

함수에서는 'kim' 타입만 입력할 수 있다고 선언해놓고, string 타입인 something.name을 파라미터로 전달했기 때문이다. 해당 에러를 해결하려면 처음부터 object의 타입을 정확히 정해놓거나, as 'kim'과 같이 assertion을 사용하면 된다.

그리고 as const 라는 코드를 object 자료에 붙일 수도 있다.

let something = {
  name : 'kim'
} as const;

function foo(a : 'kim') {

}
foo(something.name)

as const는 2가지의 기능을 가지고 있다.

  1. 타입을 object의 value로 바꿔준다. (타입을 'kim'으로 바꿔준다)

  2. object안에 있는 모든 속성을 readonly로 바꿔준다 (변경하면 에러 발생)

그렇기 때문에, object를 잠구고 싶다면 as const를 사용하면 된다.

profile
Front-End Developer

0개의 댓글