[TypeScript] 유니언, 리터럴 타입과 타입 단언, 별칭

이영우·2023년 5월 23일
0

타입스크립트

목록 보기
2/5
post-thumbnail

유니언 타입

유니언 타입은 기존에 있던 타입들을 조합하여 새로운 타입을 만드는 것이다.

function loggingId(id: number | string) {
  console.log(id);
}

loggingId(123);
loggingId('ABC');

loggingId({ myId: 'DEF' });  // error

위 예제처럼 서로 다른 두 개 이상의 타입을 사용하여 유니언 타입을 정의할 수 있다. 유니언 타입의 값은 조합의 사용된 타입 중 하나의 타입만 가질 수 있다.

function loggingId(id: number | string) {
  console.log(id.toUpperCase());
/* 
'string | number' 형식에 'toUpperCase' 속성이 없습니다.
'number' 형식에 'toUpperCase' 속성이 없습니다.
*/
}

유니언 타입의 값을 다룰 때, 유니언 타입의 모든 값에 유효한 작업일 때만 허용된다.

해결 방법?
코드에서 유니언 타입을 좁혀야(Narrowing)한다. Narrowing은 타입스크립트가 코드 구조를 바탕으로, 값을 보다 구체적으로 추론할 수 있을때 발생한다.
뭔소린가.. 싶을텐데, 아래 예제를 보면 쉽게 이해할 수 있다.

function loggingId(id: number | string) {
  if (typeof id === 'string') console.log(id.toUpperCase());
  else console.log(id);
}

위 예제에서 타입스크립트는 if문에서 id가 문자열 타입이라는 것을 알게 되고, 아니라면 else문에서 id가 숫자 타입이라는 것을 추론할 수 있게 된다.


리터럴 타입

리터럴 타입은, 구체적인 문자열과 숫자 값을 타입에서 지정할 수 있다.

let sayHello: 'Hello' = 'Hello';
sayHello = 'Hell'; // '"Hell"' 형식은 '"Hello"' 형식에 할당할 수 없습니다.

위 예제처럼 Hello 리터럴 타입의 변수에 Hell이라는 문자열을 재할당하면 오류가 나는 것을 볼 수 있다. sayHello 변수는 오직 'Hello'라는 문자열만 나타낼 수 있는 것이다.

리터럴 타입은 유니언 타입과 같이 사용했을 때 훨씬 유용한 개념들을 표현할 수 있다.

function loggingText(a: string, b: 'World' | 'Web') {
  console.log(a, b);
}

loggingText('Hello', 'World');
loggingText('Hello', 'Water');  // error
/* 
'"Water"' 형식의 인수는 '"World" | "Web"' 형식의 
매개 변수에 할당될 수 없습니다.
*/

위 예제처럼 리터럴 타입은 특정한 값만 인자로 받는 함수를 정의할 때,
리터럴이 아닌 타입과 함께 사용할 때도 사용할 수 있다.



타입 별칭 (type alias)

지금까진 객체, 유니언 타입을 사용할 때 타입을 직접 표기해주었지만, 코드를 짜다보면 한 번 이상 재사용하고 싶은 상황이 발생할 수 있다.

type Id = number | string;

// 객체 또한 가능
type SomeData = {
  a: string;
  b: number;
};

function loggingSomeData(data: SomeData) {
  // ...
}

타입 별칭은 위 예제와 같이 타입의 이름을 제공한다. 개인적으로 타입을 담은 변수를 만드는 개념이라고 생각했다.

간단하게 별칭을 선언하여 여러 곳에서 같은 타입을 재사용할 수 있다.


타입 단언

타입 단언은, 컴파일러에게 일종의 안심을 시켜주는 개념이다.
" 내가 너보다 값에 대해 더 잘 아니까, 검사하지 않아도 돼 "
라고 말하는 것과 같다. (완전 사기꾼이다)

농담이다. 개발자가 값의 타입에 대해 더 잘 아는 경우도 있다. 이런 경우는 어떤 엔티티의 실제 타입이 현재 타입보다 더 구체적일 때 발생한다고 한다.


const someValue: any = "I'm string";
const strLen: number = (someValue as string).length;

const x = 'hello' as number;  // error
/* 
'string' 형식을 'number' 형식으로 변환한 작업은 실수일 수 있습니다. 
두 형식이 서로 충분히 겹치지 않기 때문입니다. 
의도적으로 변환한 경우에는 먼저 'unknown'으로 식을 변환합니다.
*/

위 예제는 복잡한 타입을 가지고 있진 않지만, 타입 단언을 사용하면 보다 구체적인 타입을 명시해줄 수 있다.

네번째 줄 코드를 보면, 타입 단언이 모든 상황에서 허용되는 것은 아니다. 공식문서에 따르면 더 구체적인 또는 덜 구체적인 타입으로 변환하는 타입 단언만 허용된다고 나와있다.

기억해야 할 것은, 타입을 표기해주는 것과 마찬가지로 타입 단언은 자바스크립트의 런타임 동작에는 아무런 영향을 주지 않는다. (컴파일러에서만 사용)


마치며

끝이다! 이번 글은 분량 조절이 성공적이라 다행이다. 다음 타입스크립트 글에서는 아마 인터페이스 내용을 다룰 것 같다. 👍


참고 문서

profile
학습한 기술 지식들을 기록합니다.

0개의 댓글