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

Union + Omit fails and incorrectly "flattens" the type #42898

Closed
mrousavy opened this issue Feb 20, 2021 · 1 comment
Closed

Union + Omit fails and incorrectly "flattens" the type #42898

mrousavy opened this issue Feb 20, 2021 · 1 comment

Comments

@mrousavy
Copy link

Bug Report

Hi!
I'm having a type that allows the user to provide a type + resourceId + size (all required).
Once the user also passes a overrideURI parameter, the type + resourceId + size props become optional.

This works out great, but once I start using Omit<> on that type to remove a property that is contained in both types I get an error.

Here's a TS playground with a minimal reproducable sample: www.typescriptlang.org/play?.......

🔎 Search Terms

  • Union + Omit
  • Failing by incorrectly flattening
  • Joined optionals
  • string is not assignable to undefined

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about unions

⏯ Playground Link

Playground link with relevant code

💻 Code

export type WithOptional<T, TProps extends keyof T> = Partial<Pick<T, TProps>> &
  Omit<T, TProps>;

export type WithRequired<T, TProps extends keyof T> = Required<
  Pick<T, TProps>
> &
  Omit<T, TProps>;
  
interface CuventImagePropsBase {
  resourceId: string;
  type: "profile" | "group";
  size?: "full" | "thumbnail";
  
  style: Record<string, unknown>;
}

export type CuventImageProps =
  | ({
      overrideURI: string;
    } & WithOptional<CuventImagePropsBase, "type" | "resourceId" | "size">)
  | ({
      overrideURI?: undefined;
    } & WithRequired<CuventImagePropsBase, "type" | "resourceId" | "size">);

const CuventImage = (props: CuventImageProps): React.ReactElement | null => null;

interface AppProps {
    // THIS OMIT CAUSES THE PROBLEMS BELOW
    imageProps: Omit<CuventImageProps, 'style'>;
}
function App(props: AppProps) {
    // Types of property 'overrideURI' are incompatible.
    //    Type 'string' is not assignable to type 'undefined'.
    return <CuventImage {...props.imageProps} />
}

🙁 Actual behavior

The Omit<> call causes the TS union to be flattened incorrectly and makes the overrideURI parameter behave incorrectly.

🙂 Expected behavior

I expect it to behave exactly like without the Omit<>, just the style prop (prop that I omitted) should be missing.

@mrousavy
Copy link
Author

Looks like this is intentional: #31501

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

No branches or pull requests

1 participant