npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kakasoo/deep-strict-types

v2.0.11

Published

typescript utility types including deep-strict-omit and pick type

Readme

@kakasoo/deep-strict-types

npm version License: ISC TypeScript

Type-safe Pick, Omit, and key extraction for deeply nested TypeScript objects and arrays.

한국어 설명

example

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:

// AI-generated code: looks fine, but "prce" is a typo
function getTotal(order: Order) {
  return order.items.map(i => i.prce); // no error with loose types
}

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'>;

// Now AI gets a precise error:
// Type '"items[*].prce"' is not assignable to
//   type '"items" | "items[*]" | "items[*].price" | "customer" | "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[];
  }[];
};

// Extract all nested key paths
type Keys = DeepStrictObjectKeys<User>;
// "id" | "profile" | "profile.name" | "profile.age" | "posts" | "posts[*].title" | "posts[*].tags"

// Pick only what you need
type NameOnly = DeepStrictPick<User, 'profile.name'>;
// { profile: { name: string } }

// Remove what you don't need
type NoAge = DeepStrictOmit<User, 'profile.age'>;
// { id: string; profile: { name: string }; posts: { title: string; tags: string[] }[] }

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>;
// "user" | "user.name" | "user.address" | "user.address.city" | "user.address.zip"
type WithArray = { items: { name: string; price: number }[] };

type Keys = DeepStrictObjectKeys<WithArray>;
// "items" | "items[*].name" | "items[*].price"

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'>;
/*
  {
    user: {
      profile: { name: string };
      posts: { meta: { likes: number } }[];
    };
  }
*/

DeepStrictOmit<T, K>

Creates a new type by removing the specified nested keys.

type Omitted = DeepStrictOmit<Example, 'user.profile.email' | 'user.posts[*].meta.shares'>;
/*
  {
    user: {
      id: string;
      profile: { name: string; age: number };
      posts: { title: string; content: string; meta: { likes: number } }[];
    };
  }
*/

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>;
/*
  {
    user: {
      id: string;
      profile: { name: string; email: string };
      settings: { theme: string };
    };
  }
*/

Arrays of objects are also merged element-wise:

type Merged = DeepStrictMerge<{ a: number }[], { b: string }[]>;
// { 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'>;           // string
type T2 = GetType<Data, 'user.posts'>;           // { title: string; tags: string[] }[]
type T3 = GetType<Data, 'user.posts[*].title'>;  // string
type T4 = GetType<Data, 'user.posts[*].tags'>;   // string[]

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>;
// { createdAt: string; user: { name: string; birthDate: string } }

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>;
// { id: string; profile: { email: string } }

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 } });
// ["a", "a.b", "a.c"]

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');
// { user: { name: 'Alice' } }

Utility Types

| Type | Description | Example | |------|-------------|---------| | 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