any와 unknown

🌊·2023년 4월 26일
0

JS&TS

목록 보기
2/6
post-thumbnail

이전에 타입스크립트 코딩 컨벤션 관련 내용을 작성하면서 궁금한 점이 생겼습니다.

any 혹은 unknown 두 타입은 잘 사용하지 않지만, 어떤 타입을 사용하는게 맞는지에 대한 내용을 다루는 컨벤션이 많았습니다.
그 중에서 우아한형제들 기술블로그에서 해당 내용에 대해서 굉장히 자세하게 작성해주신 내용을 공부 겸 정리해보려고 합니다.
덕분에 any vs unknown을 비롯해서 컨벤션과 관련해서 많은 지식들을 배울 수 있어서 좋았습니다. 👍

짧은 결론은 두 타입 모두 사용하지 않는 것이 좋습니다. 🙅‍♂️

하지만 왜 사용하지 않아야 하는지, 어떠한 차이가 있는지는 알고 사용하지 않는 것이 좋을 것 같습니다

any vs unknown

any

  • tsconfig에서 stricttrue로 설정하거나, noImplicitAnytrue로 설정하면, 각종 변수에 타입을 지정하지 않았을 때 에러가 발생한다.
  • 타입스크립트에서 기본적으로 타입 추론을 하는데, 추론한 근거가 없으면 암시적으로 any로 할당된다.
  • strict 를 지정하지 않으면 계속 any가 쌓이게 될꺼고 anyScript가 될 수 있다.
  • 이러면 자바스크립트를 쓰는 것과 다르지 않아서 권장하지 않는다.

unknown

  • unknown도 마찬가지로 어떠한 타입이든 다 올 수 있지만, 이후 동작에 대한 제어가 가능하다.
const sayNumber = (num: number) => {
  console.log('num: ', num)
}

const sum = (a: any, b: any): any => a + b
const three = sum(1, 2)
sayNumber(three)

const minus = (a: any, b: any): unknown => a - b
const five = minus(7, 2)
sayNumber(five) // 'unknown' 형식의 인수는 'number' 형식의 매개 변수에 할당될 수 없습니다.

코드 설명

  • three의 타입은 any
  • five의 타입은 unknown
  • sayNumber 함수에 three를 넣게 되면 3이 출력
  • sayNumberfive를 넣게 되면 unknown 타입은 number 타입의 매개변수에 할당할 수 없음

sayNumber(five)를 제대로 사용하기 위해서는

  • minus 함수의 타입을 number로 명확하게 지정한다.
  • fiveas number로 타입 단언을 한다.

의 방식을 이용할 수 있습니다.

물론 이렇게 하는 것보다 제네릭을 사용하는게 일반적입니다.
any, unknown 모두 아무 타입이나 들어갈 수 있지만, unknown은 사용하는 쪽에서 처리를 강제해서 안전하게 사용할 수 있게 해줍니다

unknown의 역할

  • 해당 타입으로 지정된 값을 사용할 때가 되면 그 타입이 어떤 타입인지 명확히 알아야 사용할 수 있게 막아주는 역할을 합니다.

unknown을 사용해야 하는 상황

  • 적은 상황이지만 unknown은 예제와 같이 사용할 케이스가 있다.
const isNil = (param: unknown): boolean => param === null || param === undefined

param을 받아서 null인지 undefined인지 확인해서 true/false를 반환하는 함수입니다.

단순히 null인지 undefined인지 체크만 하면 되기 때문에 어떠한 타입이 들어올지 몰라도 됩니다.
이때는 any를 사용할수도 있습니다. 프로젝트 설정에 따라서 any를 아예 사용하지 못하게 하는 경우가 있는데 이러한 경우에 unknown 타입이 적절하다고 생각합니다.

unknown 사용 예시

function prettyPrint(x: unknown): string {
  if (Array.isArray(x)) {
    return "[" + x.map(prettyPrint).join(", ") + "]"
  }
  if (typeof x === "string") {
    return `"${x}"`
  }
  if (typeof x === "number") {
    return String(x)
  } 
  return "etc."
}

xany로 했을 경우 map(), join()을 사용할 수 있는데 unknown일 때 x가 배열인 경우에만 map(), join()을 사용할 수 있도록 강제해줍니다.

결론

  • any는 아무때나 쓸 수 있지만, 타입스크립트를 쓰는 의미가 없게 되버릴 수 있다.
  • unknown을 어쩔 수 없이 써야할 상황이 있을 수 있으나, 이를 사용하는 쪽에서 방어처리를 해서 안전하게 사용이 가능하다.

누군가는 다른 의견이 있을 수 있습니다.

이러한 내용에 대해서는 100% 정답이 없는 것 같습니다.
enum, 세미콜론(;) 사용, any vs unknown 처럼 다양한 의견이 나올 수 있죠.

자신만의 확실한 의견이 있다면 어떠한 방식이든 문제가 되지는 않는 것 같습니다! 💪

출처

0개의 댓글