The Wayback Machine - https://web.archive.org/web/20210307093117/https://github.com/microsoft/TypeScript/issues/31104
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
DanielRosenwasser opened this issue Apr 24, 2019 · 8 comments · May be fixed by #42524
Open

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

DanielRosenwasser opened this issue Apr 24, 2019 · 8 comments · May be fixed by #42524

Comments

@DanielRosenwasser
Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Apr 24, 2019

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.

@weswigham
Copy link
Member

@weswigham weswigham commented Apr 24, 2019

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]};

❤️

@DanielRosenwasser
Copy link
Member Author

@DanielRosenwasser DanielRosenwasser commented Apr 25, 2019

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

@DanielRosenwasser DanielRosenwasser changed the title 'Omit' should alias its own conditional for display 'Omit' should alias a distinct mapped type (for display purposes) Apr 25, 2019
@DanielRosenwasser
Copy link
Member Author

@DanielRosenwasser DanielRosenwasser commented May 1, 2019

Looks like this is getting reverted because of #31190.

@jcalz
Copy link
Contributor

@jcalz jcalz commented May 3, 2019

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

@DanielRosenwasser
Copy link
Member Author

@DanielRosenwasser DanielRosenwasser commented Sep 21, 2020

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 @ahejlsberg's pull request at #40633.

@DanielRosenwasser
Copy link
Member Author

@DanielRosenwasser DanielRosenwasser commented Sep 21, 2020

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

@DanielRosenwasser
Copy link
Member Author

@DanielRosenwasser DanielRosenwasser commented Sep 21, 2020

Also, @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.

@ExE-Boss
Copy link
Contributor

@ExE-Boss ExE-Boss commented Sep 22, 2020

For TS 4.0 and older, you can use @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
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

6 participants