unknown
vs never
TS Playground - An online editor for exploring TypeScript and JavaScript
정의: unknown
은 any
와 유사하지만 더 안전한 타입으로, 타입이 확정되기 전까지는 어떤 조작도 허용되지 않는 타입이다.
사용 용도: 주로 API 호출이나 JSON 파서를 감싸는 것과 같이 동적 데이터의 타입을 처리할 때 사용되며, 타입 안전성을 유지하는 데 유리하다.
모호함과 세부사항의 차이: any
타입은 어떤 타입이든 허용하지만, unknown
타입은 해당 값을 사용하기 전에 그 타입을 확정해야 한다.
예시:
1️⃣ JSON 파서
const jsonParser = (jsonString: string) => JSON.parse(jsonString);
const myAccount = jsonParser(`{ "name": "Dorothea" }`);
myAccount.name; // 정상 동작 (any 타입)
myAccount.email; // 정상 동작 (any 타입)
const jsonParserUnknown = (jsonString: string): unknown => JSON.parse(jsonString);
const myOtherAccount = jsonParserUnknown(`{ "name": "Samuel" }`);
myOtherAccount.name; // 오류 발생 (unknown 타입)
unknown
타입을 반환하는 jsonParserUnknown
은 사용자가 적절한 타입 선언을 하지 않는 한 사용할 수 없다. API를 사용하는 사람이 타입을 정의하도록 강제한다.Unkown Type 좁히기
1️⃣ typeof, instanceof:
function stringifyForLogging(value: unknown): string {
if (typeof value === "function") {
// Within this branch, `value` has type `Function`,
// so we can access the function's `name` property
const functionName = value.name || "(anonymous)";
return `[function ${functionName}]`;
}
if (value instanceof Date) {
// Within this branch, `value` has type `Date`,
// so we can call the `toISOString` method
return value.toISOString();
}
return String(value);
}
2️⃣ 타입 확정:
type User = { name: string };
const myUserAccount = jsonParserUnknown(`{ "name": "Samuel" }`) as User;
console.log(myUserAccount.name); // "Samuel" 정상 동작
3️⃣ 타입 판별자:
/**
* A custom type guard function that determines whether
* `value` is an array that only contains numbers.
*/
function isNumberArray(value: unknown): value is number[] {
return (
Array.isArray(value) && value.every(element => typeof element === "number")
);
}
const unknownValue: unknown = [15, 23, 8, 4, 42, 16];
if (isNumberArray(unknownValue)) {
// Within this branch, `unknownValue` has type `number[]`,
// so we can spread the numbers as arguments to `Math.max`
const max = Math.max(...unknownValue);
console.log(max);
}
never
는 코드가 절대 실행되지 않음을 나타내는 타입으로, 예외를 던지거나 불가능한 상황을 표현할 때 사용된다.never
타입은 절대로 발생할 수 없는 상황을 표현할 때 사용된다. 예를 들어, 아래 함수는 항상 예외를 던지고 절대 값을 반환하지 않기 때문에 never
타입을 반환한다.const neverReturns = (): never => {
throw new Error("Always throws, never returns");
};
never
타입은 switch
문에서 모든 가능한 경우를 처리했는지 보장하는 데 유용하다. 예를 들어, enum
의 모든 값을 처리해야 할 때 never
타입을 사용하여 누락된 케이스를 감지할 수 있다.enum Flower {
Rose,
Rhododendron,
Violet,
Daisy,
Tulip? // 새로운 값 추가
}
const flowerLatinName = (flower: Flower) => {
switch (flower) {
case Flower.Rose:
return "Rosa rubiginosa";
case Flower.Rhododendron:
return "Rhododendron ferrugineum";
case Flower.Violet:
return "Viola reichenbachiana";
case Flower.Daisy:
return "Bellis perennis";
default:
const _exhaustiveCheck: never = flower;
return _exhaustiveCheck;
// Type 'Flower' is not assignable to type 'never'.(2322)
}
};
never
: never
타입은 교차 타입에서 자동으로 제거된다. never
는 어떤 값도 가질 수 없기 때문에 never
가 실질적으로 타입에 영향을 미치지 않기 때문이다. 따라서 NeverIsRemoved
는 결국 string | number
타입으로 간주된다.type NeverIsRemoved = string | never | number;
// NeverIsRemoved는 string | number 타입과 동일
is
vs as
is
: Type Predicates (타입 판별자)정의: is
는 사용자 정의 타입 가드를 정의할 때 사용하는 키워드로, 특정 조건이 참일 경우 변수의 타입을 좁혀준다.
사용 용도: 함수 내에서 타입을 좁혀 특정 조건에서 타입을 확정할 때 사용된다.
예시:
1️⃣
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
if (isFish(pet)) {
pet.swim(); // 여기서 pet은 Fish로 좁혀짐
} else {
pet.fly(); // 여기서 pet은 Bird로 좁혀짐
}
2️⃣
/**
* A custom type guard function that determines whether
* `value` is an array that only contains numbers.
*/
function isNumberArray(value: unknown): value is number[] {
return (
Array.isArray(value) && value.every(element => typeof element === "number")
);
}
const unknownValue: unknown = [15, 23, 8, 4, 42, 16];
if (isNumberArray(unknownValue)) {
// Within this branch, `unknownValue` has type `number[]`,
// so we can spread the numbers as arguments to `Math.max`
const max = Math.max(...unknownValue);
console.log(max);
}
주의 사항:
as
: Type AssertionsTS Playground - An online editor for exploring TypeScript and JavaScript
as
는 특정 값의 타입을 개발자가 명시적으로 지정하는 방법이다.const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
as
:is
:코드 출처 및 참고 자료