Skip to content

OmitOptional and OmitOptionalDeep: Removes non-required keys from an object. #1426

Description

@cprecioso

Type description + examples

type Config = { required: string, optional?: string }

// This one already exists
type FullConfig = Required<Config> // -> { required: string, optional: string }

// So, I'm suggesting to make a complementary one
type MinimalConfig = OmitOptional<Config> // -> { required: string }

Our usecase is that we're writing tests for our configuration parsing, so we want to test out cases where we give the function the minimum possible configuration, and assert what's computed from it. We'd love to have type enforcement that we're not adding extra keys in this "MinimalConfig" testing.

Type source

We're currently using this

https://github.com/wasp-lang/wasp/blob/5398d01fca789bf6c42979155d4f38bcd09d92f1/waspc/data/packages/wasp-config/__tests__/spec/testFixtures.ts#L536-L562

/**
 * Recursively strips optional properties from T.
 * - Branded types are passed through (don't recurse into the brand).
 * - Arrays recurse into element type.
 * - Objects keep only required keys (collapse to EmptyObject when none remain).
 * - Primitives pass through.
 */
export type MinimalConfig<T> =
  T extends Branded<unknown, unknown>
    ? T
    : T extends Array<infer Item>
      ? Array<MinimalConfig<Item>>
      : T extends object
        ? keyof T extends never
          ? EmptyObject
          : MinimalConfigObject<T>
        : T;

type MinimalConfigObject<T> = {
  [K in keyof T as EmptyObject extends Pick<T, K> ? never : K]: MinimalConfig<
    T[K]
  >;
} extends infer Result
  ? Result extends EmptyObject
    ? EmptyObject
    : Result
  : never;

Search existing types and issues first

  • I tried my best to look for it

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions