본문 바로가기
Typescript

(Union | any | unknown) 타입들, 안전하게 코딩하기 위한 Narrowing과 Assertion에 대한 짧은 이야기

by 루에 2021. 12. 29.
반응형

특수한 타입으로 볼 수 있는 세가지 타입에 대해 이야기한다.

Union은 여러개의 타입 중 하나가 들어갈 수 있는 것(or 개념)

any는 js처럼 모든 타입을 허용한다. 연산 등에서도 에러를 뱉지 않기 때문에 사실상 ts를 사용하는 의미를 상실한다.

unknown은 any와 용도가 비슷하지만 몇가지 상황에 대해 타입 체크를 하여 연산 등을 허용하지 않아 더 안전하다. any를 사용해야 한다면 unknown으로 하자.

예제는 아래

// 여러가지를 쓸 수 있는 유니온타입
type Union = (string | number | boolean)[]
let members: Union = [1,2,3,'lim',true];

// 아무거나 다 되는 애니타입
// 타입스크립트의 의미가 없어진다.
let ay: any;
ay = 'sdf';
ay = 234;   // 다 가능

// 애니랑 비슷한 언노운 타입
// any랑 용도는 비슷하지만 더 안전하다.
let un: unknown;
un = 234;
un = 'swneif';

// 언노운이 더 안전한 이유1
//  let variable1: string = un; // un은 unknown이므로 에러
//  let variable2: string = ay; // ay는 any라 에러 안남

// 언노운이 더 안전한 이유2
// 숫자 연산 등을 막아준다.
//  un - 1; // 에러
//  ay - 1; // 에러 안남

// 타입스크립트는 연산에 엄격함
let age1 : string | number;
//  age1 + 1;   // 에러남. 유니온타입은 새로운 타입을 만들어내는 것이므로, +1 연산이 없기 때문.

let age2 : unknown = 1;
//  age2 - 1;   // 에러남. unknown은 숫자 연산 불가능

 

기본적으로 ts로 코드를 작성할 때, 안전을 위하여 Narrowing이나 Type Assertion의 규칙을 적용하여 작성한다는 듯하다. 내용을 살펴보면 각각은 아래와 같다.

Narrowing : typeof, in, instanceOf 등으로 파라미터의 타입을 체크해가며 로직을 작성한다.

Assertion : as 혹은 !를 붙여 타입을 검사해가며 로직을 작성한다.

 

두 가지 모두 kotlin에서 사용되는 개념이고 사용 방법도 동일하기 때문에 익숙한 문법이긴하나, 경험상 Assertion은 정말 확실한 것에만 잘 써야 한다. 그렇지 않으면 오히려 에러를 뿜을 수가 있다.

Narrowing은 참... 귀찮다 귀찮아. 차라리 typescript를 더 엄격하게 해서 java나 kotlin처럼 만드는게 나을 것도 같다.

 

예제는 아래와 같다.

// Narrowing

// number 타입을 보고 특정한 타입으로 보는 것
function padLeft(padding: number | string, input: string) {
  // type이 number인 경우만 아래 분기를 태운다.
  if (typeof padding === "number") {
    return new Array(padding + 1).join(" ") + input;
  }
  return padding + input;
}

// Assertion

const getArea2 = (shape: Shape) => {
  if (shape.kind === 'circle') {
  	// shape.radious가 비어있는 값이면 에러가 날 것이다. !는 값이 확실하게 있을 때 사용한다.
    return Math.PI * shape.radious! ** 2;
  }
  // as를 통해 값의 타입을 확정한다. 타입변환이 안되는 값이 들어있었다면 에러가 날 것이다.
  if (shape.kind as square === 'square') {
    return shape.sideLength! ** 2;
  }

  return null;
}

// 아래와 같은 방법으로 사용도 가능하다
type NewType = {
	id: string,
    count: number
}
function convertNewType<T>(param: { id: string, count: number }): T {
	return JSON.parse(param) as T;
}
const value = convertNewType<NewType>({id: "id", count: 5});

 

 

 

자세한 내용은 아래 블로그를 참조. 두 가지 개념 모두 설명하고 있다. 바로 위 예제 코드도 아래 블로그에서 일부 발췌하였다.

https://velog.io/@devstefancho/typescript-Narrowing

 

반응형

댓글