Typescript day1

dongEon·2025년 8월 18일
0

typescript

목록 보기
1/2
post-thumbnail

타입스크립트의 기본 문법 너머에는 실무에서 빛을 발하는 '타입 설계'의 영역이 있다는 것을 깨달았습니다. 이 문서는 AI라는 페어 프로그래머와 함께, 수박 겉핥기 수준에 머물러 있던 저의 타입스크립트 지식을 실무에 바로 적용할 수 있는 단단한 역량으로 발전시키는 여정을 기록한 것입니다.


📌 keyof와 typeof를 이용한 안전한 경로 추출

문제

const routes = {
  home: "/",
  users: "/users",
  settings: "/settings",
} as const;

type RouteName = keyof typeof routes;

function toPath(name: RouteName) {
  return routes[name];
}

// ✅ 통과
toPath("home");
toPath("users");

// ❌ 컴파일 에러 발생해야 함
toPath("login");
toPath("logout");

사용된 문법 설명

  • typeof: 변수의 타입을 추론해 타입 시스템에서 사용 가능하게 만듦
  • keyof: 객체 타입의 키를 유니온 타입으로 추출

📌 Record를 사용한 안전한 필드 매핑

문제

interface User {
  id: number;
  name: string;
  email: string;
  createdAt: string;
}

const userFieldLabels: Record<keyof User, string> = {
  id: 'User ID',
  name: 'Name',
  email: 'Email',
  createdAt: 'Created',
};

사용된 문법 설명

  • Record<K, V>: K를 키로, V를 값으로 갖는 객체 타입 생성
  • keyof T: 타입 T의 모든 키를 유니온 타입으로 추출

📌 Omit을 활용한 민감 정보 제거

문제

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  token: string;
}

type PublicUser = Omit<User, 'password' | 'token'>;

const safeUsers: PublicUser[] = [
  {
    id: 1,
    name: 'Alice',
    email: 'alice@email.com'
  },
  {
    id: 2,
    name: 'Bob',
    email: 'bob@email.com'
  },
];

사용된 문법 설명

  • Omit<T, K>: 타입 T에서 속성 K를 제거한 타입 생성

📌 유니언 타입 분기와 never를 활용한 안전한 분기 처리

문제

type LinkProps = {
  variant: 'link';
  label: string;
  href: string;
  onClick?: never;
};

type ButtonProps = {
  variant: 'button';
  label: string;
  onClick: () => void;
  href?: never;
};

type Props = LinkProps | ButtonProps;

function Render(p: Props) {
  if (p.variant === 'link') {
    return `<a href="${p.href}">${p.label}</a>`;
  } else {
    return `<button>${p.label}</button>`;
  }
}

사용된 문법 설명

  • 유니언 타입(Union Type): 여러 타입 중 하나의 타입을 가질 수 있음
  • never: 절대 사용되어서는 안 되는 값 또는 타입을 나타냄
  • 타입 좁히기(Narrowing): 조건문 등을 통해 유니언 타입을 구체적으로 좁히는 타입 보호 기법

📌 조건부 타입으로 API 응답 형태 제어하기

문제

interface ApiResponse<T> {
  data: T;
  meta: { total: number };
}

type FetchResult<T, Raw extends boolean> = Raw extends true ? ApiResponse<T> : T;

async function fetchData<T, Raw extends boolean>(
  url: string,
  opts: { raw: Raw }
): Promise<FetchResult<T, Raw>> {
  const response = {
    data: null as unknown as T,
    meta: { total: 0 },
  };

  return opts.raw ? response as FetchResult<T, Raw> : response.data as FetchResult<T, Raw>;
}

사용된 문법 설명

  • 조건부 타입(Conditional Type): A extends B ? X : Y 형태로 타입 분기
  • 제네릭 제약(Generic Constraint): Raw extends boolean 처럼 타입 조건을 제한

✅ 마무리

이번 학습에서는 단순히 문법을 외우는 것이 아니라, 문제를 풀고 타입 에러를 해결하는 과정을 통해 자연스럽게 고급 타입 문법에 익숙해질 수 있었습니다.

아직 배울 것이 많고 미숙한 점도 많지만, 조금씩 성장하고 있다는 감각을 놓지 않고 계속해서 기록을 이어가보려 합니다.

타입은 문법이 아니라 설계입니다.
그리고 설계는 연습과 시행착오를 통해 단단해집니다.

다음 학습 기록도 기대해주세요 🙌

profile
개발 중에 마주한 문제와 해결 과정, 새롭게 배운 지식, 그리고 알고리즘 문제 해결에 대한 다양한 인사이트를 공유하는 기술 블로그입니다

0개의 댓글