-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Interface extension with omit produce incoherent results: Omit<C | D, 'a'> !== Omit<C, 'a'> | Omit<D, 'a'> #42680
Comments
You don't have this issue in your |
See also #39556 (search terms |
Hence, any union that is passed as the first type to Omit, is being considered as an intersection instead, as I was supposing 🤔 I think this is something that needs to be documented, as it's very very counterintuitive, and nothing allows to think so in the docs: https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys |
Thanks a lot, I'm checking how the workaround works 😊 👍 |
For reference, using the suggested workaround by @IllusionMH, it works as I intended: // ---------------------------------------------------------------------------------------------------------------------------------------
// By: Andrii Dieiev
// From: https://github.com/microsoft/TypeScript/issues/39556#issuecomment-656925230
type BetterOmit<T, K extends string | number | symbol> = T extends unknown ? Omit<T, K> : never;
// ---------------------------------------------------------------------------------------------------------------------------------------
interface Basic {
a: string;
b: number;
}
interface BasicPlusC extends Basic {
c: string;
}
interface BasicPlusD extends Basic {
d: string;
}
type BasicPlusCOrD = BasicPlusC | BasicPlusD;
type BasicPlusCOrDMinusA = BetterOmit<BasicPlusCOrD, 'a'>;
const getUnknown = (): BasicPlusCOrDMinusA => (
Math.random() > .5 ?
{ b: 0, c: ""} // <-- Now works as intended
: { b: 0, d: ""}
);
const getUnknownBis = (): Omit<BasicPlusC, 'a'> | Omit<BasicPlusD, 'a'> => (
Math.random() > .5 ?
{ b: 0, c: ""}
: { b: 0, d: ""}
);
const main = (): void => {
getUnknown();
getUnknownBis();
};
main(); Still, I suggest updating the docs to mention this unexpected behaviour and the workaround as well (or even include it in the language with a different name, like UnionOmit, or something alike) |
Bug Report
🔎 Search Terms
wrong set theory omit
🕗 Version & Regression Information
ts-node-dev ver. 1.1.1 (using ts-node ver. 9.1.1, typescript ver. 4.1.3)
⏯ Playground Link
Playground link with relevant code
💻 Code
🙁 Actual behavior
Running this code causes the following error:
🙂 Expected behavior
I would have expected both functions,
getUnknown
andgetUnknownBis
to work correctly. This is because I'm expecting the typing system to follow the same rules as set theory. In this case I have one function,getUnknown
, whose return type structure is({ a, b, c } | ({ a, b, d, }) \ { a })
which means that the resulting structure should be in the form{ b, c } | { b, d }
.In the other function,
getUnknownBis
, the return type structure is({ a, b, c } \ { a }) | ({ a, b, d, }) \ { a })
which means that the resulting structure should be again in the form{ b, c } | { b, d }
.Hence I would expect both to work in the same way, but it looks like the first function is only expecting to return
{ b }
, instead of{ b, c } | { b, d }
. This makes me think that the type inference engine is doing{ b, c } & { b, d }
instead.The text was updated successfully, but these errors were encountered: