@kakasoo/deep-strict-types

Type-safe Pick, Omit, and key extraction for deeply nested TypeScript objects and arrays.
한국어 설명

Why in the AI Era?
AI writes more code than ever — and makes more subtle mistakes than ever. This library serves as a compile-time guardrail for AI-generated code.
The Problem
AI coding tools often produce code that looks correct but has subtle type mismatches in deeply nested structures:
function getTotal(order: Order) {
return order.items.map(i => i.prce);
}
The Solution
With strict deep types as constraints, the TypeScript compiler catches AI mistakes instantly:
import { DeepStrictPick } from '@kakasoo/deep-strict-types';
type OrderSummary = DeepStrictPick<Order, 'items[*].price' | 'customer.name'>;
AI Self-Correction Loop
When used with tsc or tsx in a build loop, AI agents can read the type error, understand exactly what went wrong, and fix it automatically:
AI generates code → tsc compile → type error → AI reads error → AI self-corrects → recompile
The stricter your types, the better the error messages, and the faster AI converges on correct code. In an AI-driven workflow, deep strict types aren't overhead — they're the safety net.
Installation
npm install @kakasoo/deep-strict-types
Quick Start
import { DeepStrictObjectKeys, DeepStrictPick, DeepStrictOmit } from '@kakasoo/deep-strict-types';
type User = {
id: string;
profile: {
name: string;
age: number;
};
posts: {
title: string;
tags: string[];
}[];
};
type Keys = DeepStrictObjectKeys<User>;
type NameOnly = DeepStrictPick<User, 'profile.name'>;
type NoAge = DeepStrictOmit<User, 'profile.age'>;
Core Types
DeepStrictObjectKeys<T>
Extracts all keys from a nested object as a union of dot-notation string paths. Arrays use [*] notation.
type Example = {
user: {
name: string;
address: { city: string; zip: number };
};
};
type Keys = DeepStrictObjectKeys<Example>;
type WithArray = { items: { name: string; price: number }[] };
type Keys = DeepStrictObjectKeys<WithArray>;
DeepStrictPick<T, K>
Creates a new type by selecting only the specified nested keys, preserving the object structure.
type Example = {
user: {
id: string;
profile: { name: string; age: number; email: string };
posts: { title: string; content: string; meta: { likes: number; shares: number } }[];
};
};
type Picked = DeepStrictPick<Example, 'user.profile.name' | 'user.posts[*].meta.likes'>;
DeepStrictOmit<T, K>
Creates a new type by removing the specified nested keys.
type Omitted = DeepStrictOmit<Example, 'user.profile.email' | 'user.posts[*].meta.shares'>;
DeepStrictMerge<Target, Source>
Deeply merges two object types. When both types share a key, Target takes precedence.
type A = { user: { id: string; profile: { name: string } } };
type B = { user: { profile: { email: string }; settings: { theme: string } } };
type Merged = DeepStrictMerge<A, B>;
Arrays of objects are also merged element-wise:
type Merged = DeepStrictMerge<{ a: number }[], { b: string }[]>;
GetType<T, K>
Extracts the type at a specific nested path.
type Data = {
user: {
name: string;
posts: { title: string; tags: string[] }[];
};
};
type T1 = GetType<Data, 'user.name'>;
type T2 = GetType<Data, 'user.posts'>;
type T3 = GetType<Data, 'user.posts[*].title'>;
type T4 = GetType<Data, 'user.posts[*].tags'>;
DeepDateToString<T>
Recursively converts all Date types to string. Useful for representing serialized/JSON response types.
type Input = {
createdAt: Date;
user: { name: string; birthDate: Date };
};
type Output = DeepDateToString<Input>;
DeepStrictUnbrand<T>
Recursively removes branding (e.g., typia tags like Format<'uuid'>) from types, restoring base primitives.
type Branded = {
id: string & { __brand: 'uuid' };
profile: { email: string & { __brand: 'email' } };
};
type Clean = DeepStrictUnbrand<Branded>;
Runtime Functions
deepStrictObjectKeys(obj)
Runtime counterpart of DeepStrictObjectKeys. Returns an array of all dot-notation key paths.
import { deepStrictObjectKeys } from '@kakasoo/deep-strict-types';
const keys = deepStrictObjectKeys({ a: { b: 1, c: 2 } });
deepStrictAssert(obj)(key)
Curried runtime function that extracts a specific nested property, preserving the object structure. Type-safe counterpart of DeepStrictPick.
import { deepStrictAssert } from '@kakasoo/deep-strict-types';
const data = {
user: { name: 'Alice', age: 30 },
posts: [{ title: 'Hello', content: 'World' }],
};
const result = deepStrictAssert(data)('user.name');
Utility Types
DeepStrictObjectLastKeys<T> | Extracts only the leaf-level (deepest) keys | "a.b.c" instead of "a" | "a.b" | "a.b.c" |
StringToDeepObject<T> | Converts a comma-separated dot-notation string to a nested object type | StringToDeepObject<"a.b,c"> = { a: { b: any }; c: any } |
Equal<X, Y> | Type-level equality check (returns true or false) | Equal<string, string> = true |
ElementOf<T> | Extracts the element type from an array | ElementOf<string[]> = string |
IsAny<T> | Checks if a type is any | IsAny<any> = true |
IsUnion<T> | Checks if a type is a union | IsUnion<string | number> = true |
ValueType | Union of all primitive types + Date | string | number | boolean | ... |
GetMember<T, Prefix> | Extracts key segments after a dot-notation prefix | Internal helper for DeepStrictOmit |
GetElementMember<T, Prefix> | Extracts array element sub-keys after a [*] prefix | Internal helper for DeepStrictOmit |
RemoveAfterDot<T, K> | Generates wildcard patterns for descendant keys | Internal helper for DeepStrictPick |
RemoveArraySymbol<T> | Strips [*] suffix from a key string | RemoveArraySymbol<"items[*]"> = "items" |
RemoveLastProperty<T> | Extracts all parent path segments | RemoveLastProperty<"a.b.c"> = "a" | "a.b" |
License
ISC