실용적인 TypeScript 팁 10가지
일상적인 개발에서 바로 적용할 수 있는 TypeScript 팁들을 소개합니다.
1. 유틸리티 타입 활용하기
TypeScript의 내장 유틸리티 타입을 적극 활용하세요.
interface User {
id: string;
name: string;
email: string;
password: string;
}
// 모든 필드를 선택적으로
type UpdateUser = Partial<User>;
// 특정 필드만 선택
type UserPreview = Pick<User, 'id' | 'name'>;
// 특정 필드 제외
type PublicUser = Omit<User, 'password'>;2. const assertion
리터럴 타입을 유지하려면 as const를 사용합니다.
// 타입: { name: string; role: string }
const user1 = { name: 'John', role: 'admin' };
// 타입: { readonly name: "John"; readonly role: "admin" }
const user2 = { name: 'John', role: 'admin' } as const;3. 타입 가드
런타임에서 타입을 좁히는 함수를 만들 수 있습니다.
interface Cat {
meow(): void;
}
interface Dog {
bark(): void;
}
function isCat(animal: Cat | Dog): animal is Cat {
return 'meow' in animal;
}
function makeSound(animal: Cat | Dog) {
if (isCat(animal)) {
animal.meow(); // Cat으로 추론됨
} else {
animal.bark(); // Dog으로 추론됨
}
}4. 제네릭 제약조건
제네릭에 제약을 걸어 더 안전한 코드를 작성하세요.
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: 'John', age: 30 };
const name = getProperty(user, 'name'); // string
const age = getProperty(user, 'age'); // number
// getProperty(user, 'email'); // Error!5. 조건부 타입
조건에 따라 다른 타입을 반환할 수 있습니다.
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false6. Template Literal Types
문자열 패턴을 타입으로 정의할 수 있습니다.
type EventName = 'click' | 'focus' | 'blur';
type EventHandler = `on${Capitalize<EventName>}`;
// 'onClick' | 'onFocus' | 'onBlur'7. satisfies 연산자
타입 체크와 타입 추론을 동시에 할 수 있습니다.
type Colors = Record<string, [number, number, number] | string>;
const colors = {
red: [255, 0, 0],
green: '#00ff00',
} satisfies Colors;
// colors.red는 튜플 타입으로 추론됨
const redValue = colors.red[0]; // number8. Discriminated Unions
공통 필드로 유니온 타입을 구분합니다.
type Success = { status: 'success'; data: string };
type Error = { status: 'error'; message: string };
type Result = Success | Error;
function handleResult(result: Result) {
if (result.status === 'success') {
console.log(result.data); // Success 타입
} else {
console.log(result.message); // Error 타입
}
}9. infer 키워드
조건부 타입에서 타입을 추론할 수 있습니다.
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function greet() {
return 'Hello';
}
type GreetReturn = ReturnType<typeof greet>; // string10. 브랜드 타입
원시 타입에 의미를 부여합니다.
type UserId = string & { readonly brand: unique symbol };
type PostId = string & { readonly brand: unique symbol };
function getUser(id: UserId) { /* ... */ }
function getPost(id: PostId) { /* ... */ }
const userId = 'user_123' as UserId;
const postId = 'post_456' as PostId;
getUser(userId); // OK
// getUser(postId); // Error! PostId는 UserId가 아님마무리
TypeScript의 타입 시스템을 잘 활용하면 버그를 미리 방지하고 더 안전한 코드를 작성할 수 있습니다.