type-fest icon indicating copy to clipboard operation
type-fest copied to clipboard

idea: Omit/PickDeep type

Open osdiab opened this issue 2 years ago • 3 comments

In my codebase we ended up with a type like this:

props: Omit<
    FilterableSelectProps<{
      value: string;
      text: string;
    }>,
    "useComboboxProps"
  > & {
    useComboboxProps: Omit<
      FilterableSelectProps<{
        value: string;
        text: string;
      }>["useComboboxProps"],
      "itemToString"
    >;
  };

The idea is to omit from FilterableSelectProps<{value: string, text: string}> the value at useComboboxProps.itemToString but expressing that ends up with a pretty hard to read type. Would be nice to have deep versions of Omit and Pick.

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • The funding will be given to active contributors.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar

osdiab avatar Jan 06 '22 08:01 osdiab

👍

sindresorhus avatar Jan 06 '22 11:01 sindresorhus

Would love to see this type.

andrewmclagan avatar Nov 25 '22 00:11 andrewmclagan

Looks like it's implemented decently soundly here (appears to still function in TS 4.8):

  • https://gist.github.com/ahuggins-nhs/826906a58e4c1e59306bc0792e7826d1

Link to SO answer featuring this:

  • https://stackoverflow.com/a/64176221/6283495

Copypasta of code, for completeness:

/** Union of primitives to skip with deep omit utilities. */
type Primitive = string | Function | number | boolean | Symbol | undefined | null

/** Deeply omit members of an array of interface or array of type. */
export type DeepOmitArray<T extends any[], K> = {
  [P in keyof T]: DeepOmit<T[P], K>
}

/** Deeply omit members of an interface or type. */
export type DeepOmit<T, K> = T extends Primitive ? T : {
  [P in Exclude<keyof T, K>]: //extra level of indirection needed to trigger homomorhic behavior
    T[P] extends infer TP ? // distribute over unions
    TP extends Primitive ? TP : // leave primitives and functions alone
    TP extends any[] ? DeepOmitArray<TP, K> : // Array special handling
    DeepOmit<TP, K>
    : never
}

/** Deeply omit members of an array of interface or array of type, making all members optional. */
export type PartialDeepOmitArray<T extends any[], K> = Partial<{
  [P in Partial<keyof T>]: Partial<PartialDeepOmit<T[P], K>>
}>

/** Deeply omit members of an interface or type, making all members optional. */
export type PartialDeepOmit<T, K> = T extends Primitive ? T : Partial<{
  [P in Exclude<keyof T, K>]: //extra level of indirection needed to trigger homomorhic behavior
    T[P] extends infer TP ? // distribute over unions
    TP extends Primitive ? TP : // leave primitives and functions alone
    TP extends any[] ? PartialDeepOmitArray<TP, K> : // Array special handling
    Partial<PartialDeepOmit<TP, K>>
    : never
}>

fmerlett-globality avatar Feb 21 '23 14:02 fmerlett-globality

Thank you @Emiyaaaaa for contributing to close this issue! ⭐

The rewards from this issue, totalling $130, has been shared with you.

What now?

  1. Create a Polar account
  2. See incoming rewards & setup Stripe to receive them
  3. Get payouts as backers finalize their payments

If you already have a Polar account setup, you don't need to do anything.

sindresorhus avatar Mar 04 '24 08:03 sindresorhus