DeepStrictTypes

소개

TypeScript로 복잡한 애플리케이션을 개발하다 보면 깊게 중첩된 객체에서도 타입 안전성을 유지하는 게 정말 어렵게 느껴질 때가 많죠. 이럴 때 딱 필요한 게 바로 DeepStrictOmit, DeepStrictPick, DeepStrictAssert 입니다. 이 유틸리티들은 TypeScript의 강력한 타입 기능을 활용해 깊게 중첩된 구조를 변형하거나 검증할 때 아주 유용하게 쓸 수 있습니다.

이 글에서는 이 세 가지 유틸리티를 하나하나 살펴보고, 다양한 사례를 통해 어떻게 활용할 수 있는지 알려드리겠습니다! 끝까지 읽고 나면 복잡한 TypeScript 구조를 더 안전하고 쉽게 다룰 수 있을 겁니다!


왜 이런 유틸리티가 필요할까요?

실제 개발 환경에서는 이런 상황들을 자주 마주하게 됩니다:

  • 깊게 중첩된 객체에서 특정 키 제거하기
  • 원하는 키만 뽑아내기
  • 동적으로 키가 존재하는지 검증하기

기존 방식으로 하면 코드가 길어지고 복잡해지기 쉬워요. 특히 타입 안전성을 유지하려면 골치 아픈 상황이 자주 생기죠. 하지만 DeepStrictOmit, DeepStrictPick, DeepStrictAssert를 사용하면 이런 문제들을 깔끔하게 해결할 수 있답니다.


DeepStrictOmit란?

DeepStrictOmit은 중첩된 객체에서 특정 키를 제거할 때 사용하는 유틸리티예요. TypeScript의 기본 Omit을 확장한 기능으로, 배열과 복잡한 구조에서도 잘 동작해요.

예제

import { DeepStrictOmit } from "./types/DeepStrictOmit";

type Example = {
  id: string;
  details: {
    name: string;
    address: {
      city: string;
      zip: string;
    };
  };
};

type Result = DeepStrictOmit<Example, "details.address.city">;
// Result: {
//   id: string;
//   details: {
//     name: string;
//     address: {
//       zip: string;
//     };
//   };
// }

주요 특징

  • 점 표기법(details.address.city)으로 원하는 깊이의 속성 제거 가능.
  • 배열도 [*] 표기법으로 다룰 수 있어요.

DeepStrictPick란?

DeepStrictPickDeepStrictOmit의 반대 역할을 하는 유틸리티입니다. 중첩된 객체에서 특정 키만 선택적으로 추출하고, 정확한 타입을 유지해줘요.

예제

import { DeepStrictPick } from "./types/DeepStrictPick";

type Example = {
  a: number;
  b: number;
  c: {
    d: string;
    e: string;
    f: {
      g: boolean;
      h: boolean;
    }[];
  }[];
};

type Result = DeepStrictPick<Example, "c[*].f[*].g">;
// Result: {
//   c: {
//     f: {
//       g: boolean;
//     }[];
//   }[];
// }

주요 특징

  • 점 표기법과 배열 표기법으로 원하는 깊이에서 키를 추출 가능.
  • 추출된 키의 타입도 정확히 유지.

DeepStrictAssert란?

DeepStrictAssert는 주어진 키가 중첩된 객체에 존재하는지 런타임에 검증하면서 타입 안전성을 보장하는 유틸리티예요. API 응답이나 사용자 입력값을 동적으로 검증할 때 특히 유용하답니다.

구현 예제

import { DeepStrictAssert } from "./types/DeepStrictAssert";

const deepStrictAssert =
  <T extends object>(input: T) =>
  <K extends DeepStrictObjectKeys<T>>(key: K): DeepStrictPick<T, K> => {
    const keys = key.split(/(?:\[\*\])?\./g).filter(Boolean);

    const traverse = (input: any, keys: string[]): any => {
      const [first, ...rest] = keys;
      if (input instanceof Array) {
        return input.map(element =>
          typeof element[first] === "object" && element[first] !== null
            ? { [first]: traverse(element[first], rest) }
            : { [first]: element[first] }
        );
      } else {
        if (typeof input[first] === "object" && input[first] !== null) {
          return { [first]: traverse(input[first], rest) };
        }
        return { [first]: input[first] };
      }
    };

    return traverse(input, keys) as DeepStrictPick<T, K>;
  };

사용 예제

interface Example {
  a: number;
  b: number;
  c: {
    d: string;
    e: string;
    f: {
      g: boolean;
      h: boolean;
    }[];
  }[];
}

const data: Example = {
  a: 1,
  b: 2,
  c: [
    {
      d: "hello",
      e: "world",
      f: [{ g: true, h: false }],
    },
  ],
};

const result = deepStrictAssert(data)("c[*].f[*].g");
console.log(result);
// Output: { c: [{ f: [{ g: true }] }] }

실제 활용 사례

  1. API 응답 데이터 처리
    • 복잡한 응답 데이터에서 필요한 필드만 추출하거나 불필요한 필드를 제거할 때.
  2. 폼 검증
    • 중첩된 폼 입력값을 동적으로 검증하면서 타입 안전성을 유지할 때.
  3. 데이터 변환
    • 데이터베이스 또는 데이터 파이프라인의 중첩 구조를 정밀하게 변형할 때.

결론

DeepStrictOmit, DeepStrictPick, DeepStrictAssert는 복잡한 TypeScript 타입을 다루는 데 있어 정말 강력한 도구입니다. 이 유틸리티들은 타입 안정성, 정밀성, 그리고 사용 편리성을 모두 제공합니다. API 개발, 데이터 변환, 폼 검증 등 다양한 분야에서 이 유틸리티가 큰 도움이 될 수 있습니다!

이 프로젝트는 비교적 새롭게 시작된 라이브러리인데, 여러분의 피드백, 기여, 그리고 버그 리포트가 이 도구를 더 발전시키는 데 큰 힘이 됩니다.

profile
자바스크립트를 좋아하는 "백엔드" 개발자

0개의 댓글