TypeScript··4 min read

실용적인 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>; // false

6. 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]; // number

8. 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>; // string

10. 브랜드 타입

원시 타입에 의미를 부여합니다.

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의 타입 시스템을 잘 활용하면 버그를 미리 방지하고 더 안전한 코드를 작성할 수 있습니다.

관련 글