Skip to content

'Omit' should alias a distinct mapped type (for display purposes) #31104

Open

Description

Today, Omit will expand to Pick<Exclude<...>, ...> in quick info, error messages, etc. which is gross.

By defining Omit as its own conditional type, we can get a slightly nicer display, though it will introduce duplication of code between the two helpers.

Activity

  1. weswigham commented on Apr 24, 2019

    @weswigham
    Member

    By defining Omit as its own conditional type, we can get a slightly nicer display, though it will introduce duplication of code between the two helpers.

    Actually it's the mapped type - you'd want to inline the Pick, not the Exclude. So:

    type Omit<T, U> = {[K in Exclude<keyof T, U>]: T[K]};

    ❤️

  2. DanielRosenwasser commented on Apr 25, 2019

    @DanielRosenwasser
    MemberAuthor

    Yeah, I figured it out as I made the change.

  3. changed the title [-]'Omit' should alias its own conditional for display[/-] [+]'Omit' should alias a distinct mapped type (for display purposes)[/+] on Apr 25, 2019
  4. DanielRosenwasser commented on May 1, 2019

    @DanielRosenwasser
    MemberAuthor

    Looks like this is getting reverted because of #31190.

  5. jcalz commented on May 3, 2019

    @jcalz
    Contributor

    Maaaaybe something like this?

    // default type parameter trickery
    type Omit<T, K extends keyof any, X extends keyof T = Exclude<keyof T, K>> = {
      [P in X]: T[X]
    };
    
    interface Test {
      required: string;
      optional?: string;
      readonly viewonly: string;
    }
    
    declare const x: Omit<Test, "required" | "optional" | "notPresent" >;
    x.viewonly = "okay"; // error!
    // Cannot assign to 'viewonly' because it is a read-only property.
    
    // typeof x is Omit<Test, "required" | "optional" | "notPresent", "viewonly">>

    Pro: The type parameter X maintains the homomorphicitinessitude that you need in the mapped type.
    Pro: The name Omit will appear instead of Pick and Exclude in IntelliSense

    Con: Default type parameters are not meant for this, who knows what could happen
    Con: IntelliSense will show the value of X which could be confusing.


    Or what about

    // conditional type inference antics
    type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>> extends infer U
      ? { [P in keyof U]: U[P] }
      : never;
    
    interface Test {
        required: string;
        optional?: string;
        readonly viewonly: string;
    }
    
    declare const x: Omit<Test, "required" | "optional" | "notPresent">;
    x.viewonly = "okay"; // error!
    // Cannot assign to 'viewonly' because it is a read-only property.
    
    // typeof x is { readonly viewonly: string; }

    Pro: Still homomomomomorphic
    Pro: The name Omit appears instead of Pick, and in the concrete cases the actual distinct mapped type shows up.

    Con: Conditional type inference isn't exactly meant for this either, who knows what can happen

  6. DanielRosenwasser commented on Sep 21, 2020

    @DanielRosenwasser
    MemberAuthor

    The following type

    type Omit<T, ExcludedKeys extends keyof any> = {
        [K in keyof T as Exclude<K, ExcludedKeys>]: T[K]
    };

    now maintains modifiers thanks to Anders Hejlsberg (@ahejlsberg)'s pull request at #40633.

  7. DanielRosenwasser commented on Sep 21, 2020

    @DanielRosenwasser
    MemberAuthor

    I think this change will be contingent on performance tests though.

  8. DanielRosenwasser commented on Sep 21, 2020

    @DanielRosenwasser
    MemberAuthor

    Also, Wesley Wigham (@weswigham) may want to weigh in since he has a PR out at #37608, but I think it would be undesirable to add a 3rd type parameter just to use a default type argument.

  9. ExE-Boss commented on Sep 22, 2020

    @ExE-Boss
    Contributor

    For TS 4.0 and older, you can use Jack Works (@Jack-Works)’s type-challenges/type-challenges#141.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Effort: ModerateRequires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual".Experience EnhancementNoncontroversial enhancementsHelp WantedYou can do thisSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions