
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란?DeepStrictPick은 DeepStrictOmit의 반대 역할을 하는 유틸리티입니다. 중첩된 객체에서 특정 키만 선택적으로 추출하고, 정확한 타입을 유지해줘요.
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 }] }] }
DeepStrictOmit, DeepStrictPick, DeepStrictAssert는 복잡한 TypeScript 타입을 다루는 데 있어 정말 강력한 도구입니다. 이 유틸리티들은 타입 안정성, 정밀성, 그리고 사용 편리성을 모두 제공합니다. API 개발, 데이터 변환, 폼 검증 등 다양한 분야에서 이 유틸리티가 큰 도움이 될 수 있습니다!
이 프로젝트는 비교적 새롭게 시작된 라이브러리인데, 여러분의 피드백, 기여, 그리고 버그 리포트가 이 도구를 더 발전시키는 데 큰 힘이 됩니다.