TypeScript의 typeof 연산자
typeof 연산자의 JavaScript, TypeScript 맥락에서의 차이점과 다양한 활용 방법
TypeScript를 사용하다 보면 typeof 연산자를 자주 마주친다. typeof는 JavaScript에도 존재하는 연산자지만, TypeScript에서는 두 가지 맥락에서 동작 방식이 달라진다.
- JavaScript의 런타임
typeof연산자 - TypeScript의 타입 연산자로서의
typeof
두 맥락의 차이를 이해하면, 값에서 타입을 안전하게 추출하고 반복적인 타입 선언을 줄일 수 있다.
typeof는 피연산자의 데이터 타입을 나타내는 문자열을 반환한다.
let value = "hello";
console.log(typeof value); // "string"
let number = 32;
console.log(typeof number); // "number"
let func = () => {};
console.log(typeof func); // "function"반환되는 값은 JavaScript의 기본 데이터 타입(boolean, number, bigint, string, symbol, null, undefined)과 function, object다.
TypeScript에서는 typeof를 type 맥락에서도 사용할 수 있다. 이때는 역할이 달라진다.
const user = {
name: "John",
age: 30,
isAdmin: true
};
const v_user = typeof user; // object
type User = typeof user;
// type User = {
// name: string;
// age: number;
// isAdmin: boolean;
// }v_user는 const 키워드로 선언된 변수에 할당되므로, 런타임에서 user의 타입을 나타내는 "object" 문자열을 반환한다. 반면 type 키워드 뒤에서 사용된 typeof는 TypeScript의 타입을 반환한다.
typeof는 값에서 타입을 추출할 때만 사용한다. 이미 타입으로 선언된 것에 사용하면 오류가 발생한다.
// 잘못된 사용
type MyString = string;
type Wrong = typeof MyString; // 오류!
// 올바른 사용
const myString = "hello";
type Correct = typeof myString; // stringconst colors = ["red", "green", "blue"] as const;
type Colors = typeof colors[number];
// type Colors = "red" | "green" | "blue"as const 없이 사용하면 넓은 타입(widened type)으로 추출되고, as const와 함께 사용하면 리터럴 타입과 readonly가 붙어서 추출된다.
// as const 없이
const config = {
endpoint: "api.example.com",
port: 3000
};
type Config = typeof config;
// type Config = {
// endpoint: string;
// port: number;
// }
// as const 사용
const config = {
endpoint: "api.example.com",
port: 3000
} as const;
type Config = typeof config;
// type Config = {
// readonly endpoint: "api.example.com";
// readonly port: 3000;
// }유틸리티 타입 ReturnType과 Parameters를 활용하면 함수의 반환 타입과 매개변수 타입을 추출할 수 있다.
function createUser(name: string, age: number) {
return { id: Date.now(), name, age };
}
type User = ReturnType<typeof createUser>;
// type User = {
// id: number;
// name: string;
// age: number;
// }
type Param = Parameters<typeof createUser>
// type Param = [name: string, age: number]
- 우아한 타입스크립트
- Typescript 핸드북