TypeScript의 unKnown과 any?

doohyunlm·2024년 4월 9일
3

TypeScript

목록 보기
2/2

TypeScriptunKnownany를 들어 보신 적 있으신가요? 이 두 가지 타입이 JavaScript 대신 TypeScript를 쓰는 이유중 상당 부분을 차지하고 있다고 생각합니다.



JavaScript 대신 TypeScript

TypeScript의 등장 배경에는 JavaScript의 유연함이 오히려 개발 단계에서 발생하는 에러들을 잡지 못하는데에 있었습니다.

Type을 선언하지 않다보니 논리적으로 말이 되지 않는 코드들도 정상적으로 동작하게 보이게 되는 것이죠

예를 들어 아래의 코드처럼 number의 값과 string의 값을 더하게 되면 check123이라는 string값을 나타나게 됩니다. type 체크를 따로 하지 않으니 string값과 더하는 number type123string으로 캐스팅해서 더한 결과 값을 도출한거죠

의도한 결과라면 상관 없지만 의도하지 않았을 경우 치명적인 오류를 내뱉을지도 모릅니다.

이것처럼 기본적으로 javascript는 모든 type에 대해 처리가 가능한 any 타입을 기반으로 만들어졌습니다.

const typeNumber = 123;
const typeString = 'Check'

const typeCheck = typeString + typeNumber;

console.log(typeCheck)

check123

아래 글처럼 type에 대한 선언을 해주게 되면 타입이 체킹되어 string + number의 합은 오류를 표출하도록 바꿔서 미리 코드 단계에서 error을 잡도록 도와줍니다.

의도한 대로 number type의 결과 값만 나오게 한것이죠. 이는 javaScript의 오류를 빠르게 잡을 수 있도록 했고 typeScript로 대다수의 프로그래머들이 넘어가는 역할을 하게 됩니다.

const typeNumber:number = 123;
const typeString:string = 'Check'

const typeCheck:number = typeString + typeNumber;
typeCheking error



any와 unknown

위에서 설명했다싶이 기본적으로 any 타입은 코딩을 함으로써 많은 유연함을 주지만 단점도 명확했습니다. 타입을 체킹하기 위해 쓰는 typeScriptany 선언으로 쓰게 되면 그 의미가 없게되는 것이죠.

하지만 개발을 하면 모든 타입을 알 수 없는 경우도 있기 마련입니다.

기본적으로 모든 type 선언해서 쓰지만 외부 api나 다른 프로그램에서 모든 type을 다 알 수 없는 경우도 있기에 any 타입을 썼던 것이죠.

그래서 나온 게 unknown 타입입니다. unknown type은 typeScript3.0.0 version에서부터 나온 타입으로 any type처럼 모든 타입을 할당해서 사용 할 수 있습니다.

let check : unknown;
check = true // OK (boolean)
check = 123 // OK (number)
check = 'check' // OK (string)
check = {} // OK (object)



그래서 어디에 활용할까?

export const isEmptyCheck = (value: unknown): boolean => {
  if (value === null || value === undefined || value === '') {
    return true;
  }

  if (value instanceof Date) {
    return isNaN(value.getTime());
  }

  if (typeof value === 'string') {
    return value.trim() === '';
  }

  if (Array.isArray(value)) {
    return value.length === 0 || value.every(isEmptyCheck);
  }

  if (typeof value === 'object' && value !== null) {
    return Object.values(value).every(isEmptyCheck);
  }

  return false;
};

간단하게 만든 null 체크 로직입니다.

다양한 type의 값을 받아야 하니 간단하게 설정할때는 any로 받아서 처리를 하면 되겠죠?

하지만 이처럼 타입을 받아서 체킹하는 것이 typeScript를 올바르게 사용한다고 할 수 있습니다.

저렇게 typeGuard 형식처럼 각각의 typeof를 통해 따로따로 그에 따른 대응을 처리할 수 있게 하는 것이죠.

TypeGuard란?
특정 범위 내에서 변수의 타입을 보다 구체적으로 좁혀나갈 수 있게 하는 기능입니다. 이를 통해 타입을 보다 정확히 추론할 수 있으며, 개발자는 타입 관련 오류를 미리 방지하고, 더 안전하게 코드를 작성할 수 있습니다. Type Guard는 크게 사용자 정의 Type Guard와 TypeScript가 제공하는 Type Guard로 나눌 수 있습니다.



실무에서는 어떤 식으로?

저 같은 경우는 type 이 어떻게 들어올지 아는 경우는 type을 다 선언해서 사용을 하고 어떤 타입이 올지 알 수 없는 경우에는 any 타입으로 처음에 로직을 설계하고 type이 어떻게 들어올지 아는 경우는 unknown 타입을 통해서 각각의 타입가드로 타입의 안정성을 확보하는 방향으로 코딩하는 것을 선호합니다.



결론

코딩 방법에는 여러가지가 있지만 본래 의미를 알고 그 의미가 코딩의 편리함을 넘어서지 않는 편에서 효율성과 안정성에 중점에 두고 코딩을 하는 것이 좋다고 생각합니다.

자신에게 맞는 방안으로 anyunknown을 활용하면 어떨까요?

틀린 점이 있다면 댓글로 남겨주세요!

여러분은 어떠신가요?

여러분의 코딩 스타일이나 방법들을 댓글로 남겨주시면 재밌는 이야기를 나눌 수 있을 것 같습니다.

profile
백엔드 개발자

2개의 댓글

comment-user-thumbnail
2024년 4월 17일

안녕하세요, 타입스크립트를 잘 몰라서 문의드립니다.
타입스크립트로 작성한 경우, TypeGuard 기능으로 if 조건의 instanceof 문법으로 Date 타입임을 유추하여 if 블록 내에서 캐스팅없이 Date 형으로 인식하고 메소드를 사용할 수 있다는 것 맞을까요?

 if (value instanceof Date) {
    // Date 형으로 인식하여 메소드 사용 시, 오류가 발생하지 않음.(컴파일러가 잡아주는지?)
    return isNaN(value.getTime());
  }

그리고 이 과정은 컴파일러를 통해 오류를 도출하는지도 궁금합니다!

1개의 답글