Skip to content

fix(lib/es5): Preserve Omit in output #35889

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

Closed
wants to merge 2 commits into from

Conversation

ExE-Boss
Copy link
Contributor

@ExE-Boss ExE-Boss commented Dec 28, 2019

I’ve been using this without problems in my local version of the TypeScript library.


Fixes #34793

@dragomirtitian
Copy link
Contributor

I am pretty sure this option was considered when Omit was added. It was rejected because it does not preserve optionality and readonly-ness. Pick is homomorphic since it maps over K where K extends keyof T and thus preserves modifiers.

Since your type maps over Exclude<keyof T, K> it is not homomorphic. Only types that map over keyof T where T is a type parameter or that map over K where K is type parameter with K extends keyof T are homomorphic.

type Omit2<T, K extends keyof any> = {
    [P in Exclude<keyof T, K>]: T[P];
};

type U = {
    a: number,
    readonly b?: number
} 

type R = Omit2<U, 'a'> // has b: number | undefined;
type R2 = Omit<U, 'a'> // has  readonly b?: number | undefined;

Playground Link

@ExE-Boss
Copy link
Contributor Author

That is probably also why auto‑fix is broken with this.

@ypresto
Copy link
Contributor

ypresto commented Jan 8, 2020

FYI:

The documentation for "homomorphic" and Pick is here: https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types


#35889 (comment)
type R = Omit2<U, 'a'> // has b: number | undefined; is actually // has b: number; (optional is NOT copied too).


I tried

type Omit2<T, K extends keyof any> = K extends keyof T ? {
  [P in Exclude<keyof T, K>]: T[P];
} : Omit<T, K>;

but does not solve the problem 😂

@ypresto
Copy link
Contributor

ypresto commented Jan 8, 2020

Then my question is: why Omit uses K extends keyof any instead of K extends keyof T? (I sometimes specify wrong or unnecessary K for Omit)

@ExE-Boss
Copy link
Contributor Author

ExE-Boss commented Jan 8, 2020

The reason is probably because this is the more correct Object.assign(…) type:

declare function __assign<T, S>(target: T, source: S): Omit<T, keyof S> & S;

To be 100% correct, the result should include properties from T that are optional in S.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Compiled .d.ts output for Omit is verbose and semantically inconsistent
3 participants