
Day 4 진도에 해당되는 강의를 듣고 unknown, never, void, any 타입에 대해 정리해보았습니다.
any, unknown, void, never 같은 타입을 이해하려면, 먼저 타입 간의 관계를 이해할 필요가 있습니다. 이때 자주 등장 하는 개념으로 슈퍼타입, 서브타입, 업 캐스팅, 다운 캐스팅이 있습니다.

슈퍼타입은 더 일반적이고 넓은 범위의 타입입니다. 여러 서브타입들을 포괄하는, 말 그대로 “상위 타입”입니다.number는 1, 2, 10, 1.5, Infinity 등 모든 숫자 값을 포함할 수 있는 타입입니다.number는 더 넓은 개념이므로 10의 슈퍼타입입니다.서브타입은 슈퍼타입보다 더 구체적이고 좁은 범위의 타입입니다.10이라는 숫자 하나만 허용하는 number literal type은 number보다 범위가 좁기 때문에, 10은 number의 서브타입입니다.let num1: number = 123;
const b: 10 = 10;
const c: 10 = 20; // ❌ Error: 20은 10의 서브타입이 아님 (다른 리터럴이기 때문)
타입 간의 변환을 설명할 때 자주 쓰이는 개념이 업 캐스팅(up casting)과 다운 캐스팅(down casting)입니다. 쉽게 말하면, 타입을 넓게 또는 좁게 바꾸는 것입니다.

const subNum: 10 = 10;
let superNum: number = 123;
superNum = subNum; // 10 -> number (업 캐스팅)
const num: number = 10;
const literal: 10 = num as 10; // number -> 10 (다운 캐스팅)
More on Functions#unknown - TypeScript Handbook 보러가기
unknown 타입은 정확한 타입을 알 수 없지만 일단 뭔가는 들어올 수 있는 타입입니다. 어떤 값이 있을 수는 있지만, 그 값의 타입을 알 수 없음을 나타냅니다. any 와 비슷해 보이지만, unknown 타입의 값은 타입을 확정하지 않으면 사용할 수 없습니다. 그래서 값을 사용하기 전에 타입을 검사해야 합니다.
let input: unknown = 'hello';
if(typeof input === 'string') {
console.log(input.toUpperCase());
}
모든 타입(any, object, void, undefined, null, never)의 값의 슈퍼타입입니다. 그래서 모든 타입의 값을 할당 받을 수 있습니다. 업 캐스팅이 가능합니다.
function handleInput(data: unknown) {
if(typeof data === 'number'){
console.log(data.toFixed(2));
}
}
unknown 타입의 값은 타입 정제 없이 직접 사용할 수 없습니다.unknown 은 타입 안전성을 유지하면서 유연하게 코딩할 수 있게 해줍니다.never 타입은 "절대 반환되지 않는 값"을 의미합니다.
예를 들어, 정상적으로 종료되지 않거나, 영원히 실행되거나, 오류를 던지는 함수가 대표적입니다.
function throwError(message: string): never {
throw new Error(message);
}
function loopFunc(): never {
while(true) {
// ...
}
}
never 타입은 아무 값도 가질 수 없는 타입이기 때문에, 모든 타입(any, unknown, object, void, undefined, null, never)의 서브타입으로 간주됩니다. 그래서 never 타입을 가진 값을 다른 타입(any, unknown, string, number, boolean 등)의 변수에 할당할 수는 있습니다.
function neverFunc(): never {
while (true) {}
}
// up casting
let anyVar: any = neverFunc();
let unknownVar: unknown = neverFunc();
let obj: { name: string } = neverFunc();
let voidVar: void = neverFunc();
let undefinedVar: undefined = neverFunc();
let nullVar: null = neverFunc();
let num: number = neverFunc();
let str: string = neverFunc();
let bool: boolean = neverFunc();
하지만 반대로, 다른 타입의 값을 never 타입 변수에 할당하는 것은 허용되지 않습니다.
let a: never = 'hello'; // ❌ Error!
a = 123; // ❌ Error!
a = false; // ❌ Error!
a = null; // ❌ Error!
a = undefined; // ❌ Error!
a = { name: 'Lucy' }; // ❌ Error!
무한 루프 등으로 종료되지 않거나 예외를 던질 때 사용합니다.// 아래 코드는 모두 Error가 발생합니다.
let never1: never = 1;
let never2: never = "string";
let never3: never = true;never로 남아 오류가 발생할 수 있습니다.More on Functions#void - TypeScript Handbook 보러가기
void는 반환값이 없다는 걸 의미하는 타입입니다. 주로 함수의 반환 타입으로 사용되며, 반환값이 없음을 명확히 합니다.
function logMessage(message: string): void {
console.log(message);
}
const arr: number[] = [1, 2, 3];
const callbackFn = (value: number, index: number): void => {
console.log(`${index + 1} 번째 요소: ${value}`);
};
arr.forEach(callbackFn);
void는 변수 타입으로는 거의 사용하지 않습니다.undefined와 유사하지만, 의도적으로 아무것도 반환하지 않는다는 의미를 담고 있습니다.void는 undefined의 슈퍼타입이라 업 캐스팅의 개념에 의해 void 함수에 return undefined는 허용됩니다.function logMessage(message: string): void {
console.log(message);
return undefined;
}Everyday Types - TypeScript Handbook 보러가기
any 타입은 TypeScript의 타입 시스템을 우회하여, 해당 변수에 어떤 타입의 값이든 할당할 수 있도록 허용하는 타입입니다. 즉, 타입 검사를 하지 않겠다는 의미로 기존의 자바스크립트를 쓰는 것과 동일합니다.
모든 타입(never를 제외한 unknown, object, void, undefined, null 타입)의 값을 할당할 수 있는 타입으로 다운 캐스팅, 업 캐스팅이 가능합니다.
let anyVar: any;
let unknownVar: unknown;
let voidVar: void = () => { console.log('hello'); };
anyVar = unknownVar;
anyVar = { name: 'Lucy' };
anyVar = voidVar;
anyVar = undefined;
anyVar = null;
anyVar = 123;
anyVar = 'hello';
anyVar.foo();
any를 사용하면 타입스크립트의 타입 시스템을 무력화 시킵니다.any 사용을 남용하면, 결국 자바스크립트와 다를 바 없는 코드가 됩니다.이번에 unknown, never, void, any 타입을 정리하면서 그동안 막연하게 알고 있던 개념들을 좀 더 확실히 이해할 수 있었습니다.
any와 void는 평소에도 종종 보며 대략적인 용도는 알고 있었지만, unknown과 never는 “이게 왜 필요하지?”, “언제 써야 하지?” 라는 의문만 남은 채 정확하게 쓰지 못했던 타입이었습니다. 이번에 강의를 듣고 정리하는 과정을 통해, 이 네 가지 타입이 각각 어떤 의미를 갖고 있고, 어떤 상황에서 사용해야 하는지를 배울 수 있었습니다.
any는 타입 검사를 하지 않고 어떤 값이든 허용하고 싶을 때 사용하지만, 타입 안정성을 잃게 되므로 실제 프로젝트에서는 지양하려고 합니다. 다만, JavaScript 프로젝트를 TypeScript로 점진적으로 마이그레이션할 때는 일시적으로 사용할 수 있을 것 같습니다.void는 함수가 아무 값도 반환하지 않을 때 사용하는 타입으로, 이번 기회에 다시 한 번 복습할 수 있었습니다.unknown은 값은 존재하지만 타입을 정확히 알 수 없을 때 사용하는 타입으로, 타입 정제를 통해 안전하게 다룰 수 있다는 점을 배울 수 있었습니다.never는 무한 루프나 예외 처리처럼 함수가 정상적으로 종료되지 않는 경우에 사용하는 타입이라는 것도 알게 되었습니다.이번 학습을 통해 앞으로 프로젝트에서 이 4가지 타입을 마주하게 되더라도, 용도나 의미를 몰라서 당황하는 일 없이 사용할 수 있을 것 같습니다.
평일 중에 이 글은 보지 못했는데..! 이번주 정말 부지런하게 공부하셨군요!
덕분에 unknown, never, any 라는 신기한 타입을 알게 되었습니다.
그나마 void 반환을 간간이 쓰는데
콜백 함수의 반환 타입으로도 자주 등장한다. 정말 그렇네요!