타입스크립트에만 있는 타입을 배우자
타입스크립트의 특수 타입 총정리 (any, unknown, void, {}, never)
타입스크립트는 자바스크립트보다 정확한 타입 검사를 지원하기 위해 몇 가지 특수 타입을 제공한다. any, unknown, void, {}, never 타입이 그것이다.
any 타입
타입 검사를 포기하는 타입. any 타입을 사용하면 모든 값이 허용 되지만 타입 스크립트의 타입 검사 장점을 무력화하기 때문에 지양해야 한다.
let value: any = "hello";
value = 123; // ✅ 가능 (문자열 → 숫자로 변경)
value = true; // ✅ 가능 (숫자 → 불리언 변경)
console.log(value.toFixed()); // 🚨 `boolean`인데도 `.toFixed()`가 실행됨 → 오류 발생 가능
any를 사용하면 잘못된 메서드 호출도 에러 없이 실행되므로 위험하다. 또한 any가 전염 되는 문제가 있는데 any 가 한 번 들어오면 이후 모든 연산이 any로 변질 된다.
타입스크립트가 명시적으로 any를 반환하는 경우도 있다. 대표적으로 JSON.parse와 fetch 함 수가 있는데, 이때는 직접 타이핑하여 any가 전염되는 것을 막아야한다.
fetch('url').then((response) => {
return response.json();
}) ,then( (result) => { // (parameter) result: any
});
const result = JSON.parse('{"hello":"json"');//const result: any
fetch('url').then<{ data: string }>((response) => {
return response.json();
}).then((result) => { // result가 { data: string } 타입임을 명시
}
const result: { hello: string } = 3S0N.parse(1{"hello":"json"') //result에 { hello: string } 타입을 직접 명시하여 타입 안정성을 높임
unknown 타입
안전한 any 대체 타입이다. unknown은 any처럼 모든 값을 받을 수 있지만 직접 조작은 불가능하고 타입 검사를 통과해야만 조작이 가능하다. unknown 타입을 직접 표시할 경우는 거의 없고, 대부분 try catch문에서 unknown이 사용 된다.
let value: unknown = "hello";
value.toUpperCase(); // 🚨 에러 발생! (`unknown` 타입은 직접 조작 불가능)
try {
} catch (e) {
console.log(e.message);-// e는 unknown 타입
}
e가 unknown이므로 그 뒤에 어떠한 동작도 수행할 수 없다. 게다가 catch문의 e에는 any와 unknown 외의 타입을 직접 표기할 수 없기 때문에 이럴 때는 as로 타입을 주장(Type Assertion) 하자.
try {
} catch (e) {
const error = e as Error;
console.log(error.message);
unknown 타입인 으를 Error 타입으로 강제 지정했다. 그 후에는 e가 Error로 인식되어 관련 기능이 동작 한다
const a: number = '123' as number;
string에서 number로 타입을 바꾸는 것은 불가능하기 때문에 에러 메시지를 띄운다. 다만 강제로 변환하는 방법이 있는데 unknown으로 주장한 후에 원하는 타입으로 다시 주장하는 것이다. 다만 강제로 주장한 것이므로 as를 사용할 때는 자기가 책임져야 한다.
const a: number = '123' as unknown as number;
이렇게 typeof를 사용하여 타입을 확인하면 안전하게 사용이 가능하다.
if (typeof value === "string") {
console.log(value.toUpperCase()); // ✅ 타입 체크 후 사용 가능
}
try-catch에서 unknown을 활용
try {
throw new Error("에러 발생!");
} catch (e) {
console.log((e as Error).message); // ✅ `as Error`로 타입 단언 후 사용
}
catch (e)의 e는 기본적으로 unknown 타입이다. as 키워드를 사용해 Error 타입으로 변환해야 안전하게 조작 가능하기 때문에 안전하다.
void 타입
반환값이 없는 경우.
function logMessage(): void {
console.log("Hello!");
}
자바스크립트에서는 undefined를 반환하지만, 타입스크립트에서는 타입을 void로 표현한다!
const func: () => void = () => 3;
console.log(func()); // ❌ 에러는 없지만, 의미 없음
void는 함수의 반환값을 무시하는 역할을 하기 때문에 반환값을 사용하지 못하도록 강제할 때 활용 된다.
{} (빈 객체 타입)
{} 타입은 null과 undefined를 제외한 모든 값이 가능하다. 객체로 오해할 수 있지만 이 타입은 null과 undefined를 제외한 모든 값을 의미한다.
const obj: {} = "hello"; // ✅ 가능
const num: {} = 123; // ✅ 가능
const bool: {} = true; // ✅ 가능
const arr: {} = []; // ✅ 가능
const func: {} = () => {}; // ✅ 가능
또한 {} 타입은 속성 접근이 불가능하다.
const obj: {} = { name: "John" };
console.log(obj.name); // ❌ 에러 발생! (속성 접근 불가능)
실제 코드에서는 거의 사용되지 않으므로 unknown을 대신 사용하자.
Object 타입
never 타입
절대 실행되지 않는 상태이다. throw, 무한 루프 같은 코드에서 발생한다.
function throwError(): never {
throw new Error("에러 발생!");
}
이 함수는 절대 정상적으로 종료되지 않기 때문에 반환 타입이 never이다.
never가 사용 되는 경우
function infiniteLoop(): never {
while (true) {
console.log("무한 루프!");
}
}
무한 루프가 종료 되지 않으므로 never 타입이 된다.
function checkType(value: string | number) {
if (typeof value === "string") {
console.log("문자열!");
} else if (typeof value === "number") {
console.log("숫자!");
} else {
value; // 🚨 여기서 value는 `never` 타입!
}
}
모든 경우를 처리했는데도 else가 존재하면 value는 never 타입이다. 실제로 실행 될 일이 없는 코드라는 의미.
타입 간 대입 가능성
타입 | any | unknown | {} | void | undefined | null | never |
any | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
unknown | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
{} | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
void | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
undefined | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
null | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ |
never | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
any는 모든 타입으로 대입 가능하지만, never는 어떤 타입도 가질 수 없다.
unknown은 모든 값을 받을 수 있지만, 대입될 수는 없다.
타입 | 설명 |
any | 모든 타입을 허용하지만 타입 검사를 포기 |
unknown | 모든 값을 받을 수 있지만 직접 사용 불가능 → 타입 검사가 필요 |
void | 함수의 반환값이 없을 때 사용 (undefined와 비슷) |
{} | 객체처럼 보이지만 null과 undefined를 제외한 모든 값 허용 |
never | 절대 도달할 수 없는 상태 (예: 무한 루프, 오류 발생 등) |