Issue 1:
After upgrading to styled-components 5.0.1 from 4.1.9, we're getting these errors.

TS2589: Type instantiation is excessively deep and possibly infinite.

I tried using the @types/styled-components package and had problems.

I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript

I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).

Mention the authors (see Definitions by: in index.d.ts) so they can respond.

Authors: @Igorbek @Igmat @Lavoaster @Jessidhia @jkillian @eps1lon @flavordaaave @wagerfield @Lazyuki @mgoszcz2

Here's a playground link that DOESN'T show the error, but this error in an actual project will definitely show. In our case, in many multiple files. Everything was fine before the update.

The error shows on text={text} {...rest} role="separator" and disappears when removing {...rest}.

All is well if I don't upgrade this package, even when I do upgrade styled-components itself.

It might help to know as well that we're on Typescript 3.8.3. Perhaps a newer typescript is stricter in some magical way, although I seriously doubt they'd introduce such impressively strange breaking changes.

Issue 2:
TypeScript Version: 3.7.2, 3.8.0-dev.20191102 (worked in 3.6)

Search Terms:

Type instantiation is excessively deep and possibly infinite.ts(2589)

Mapped types

Generics

Conditional types

Code

Note: this issue manifests itself only in our codebase. When you run the same code in TypeScript Playground, it seems to be working fine.

The snippet is hardly minimal, but I reduced it as much as I could. I recorded a video where exactly the same code yields an error different than the one in TypeScript Playground. I tried with two versions of TypeScript: 3.7.2 and 3.8.0-dev.20191102. It worked correctly with 3.6.

Since @sheetalkamat and @DanielRosenwasser have access to our repository, you're welcome to have a look at this PR. Copy-paste the code below anywhere in the project to see the error.

The versions of types used:

@types/history@4.7.3

@types/react@16.9.11

@types/react-router-dom@5.1.0

@types/recompose@0.30.7

Note: Interestingly enough, if you change:

- declare const Button: React.FunctionComponent<Omit<Props, never>>;
+ declare const Button: React.FunctionComponent<Props>;

it works again despite the fact Omit<Props, never> should be the same as just Props.

Source code

import { History } from 'history'; // "4.7.3"
import * as React from 'react'; // "16.9.11"
import { LinkProps, RouteComponentProps, withRouter } from 'react-router-dom'; // "5.1.0"
import { getDisplayName } from 'recompose'; // "0.30.7"

declare function isDefined<T>(candidate: T | null | undefined): candidate is T;
declare function isString(value?: any): value is string;

type ObjectOmit<T extends K, K> = Omit<T, keyof K>;

type OnClick = NonNullable<React.ComponentProps<'button'>['onClick']>;

type OnClickProp = {
/** If there is a custom click handler, we must preserve it. */
onClick?: OnClick;
};

type ProvidedProps = OnClickProp;

type InputProps = OnClickProp & {
/** Note: we want this helper to work with all sorts of modals, not just those backed by query
* parameters (e.g. `/photo/:id/info`), which is why this must accept a full location instead of a
* `Modal` type.
* */
to: Exclude<LinkProps['to'], Function>;
};

const buildClickHandler = ({
to,
onClick,
history,
}: InputProps & {
history: History;
}): OnClick => {
const navigate = () => {
// https://github.com/Microsoft/TypeScript/issues/14107
isString(to) ? history.push(to) : history.push(to);
};

return event => {
[onClick, navigate].filter(isDefined).forEach(callback => callback(event));
};
};

/** See the test for an example of usage. */
export const enhance = <ComposedProps extends ProvidedProps>(
ComposedComponent: React.ComponentType<ComposedProps>,
) => {
type PassThroughComposedProps = ObjectOmit<ComposedProps, ProvidedProps>;
type OwnProps = InputProps & RouteComponentProps<never> & PassThroughComposedProps;
type Props = OwnProps;

const displayName = `CreateModalLink(${getDisplayName(ComposedComponent)})`;

const ModalLink: React.FunctionComponent<Props> = ({
to,
onClick,

history,
// We specify these just to omit them from rest props below
location,
match,
staticContext,

...passThroughComposedProps
}) => {
const clickHandler = buildClickHandler({ to, onClick, history });

const composedProps: ComposedProps = {
// Note: this is technically unsafe, since the composed component may have props
// with names matching the ones we're omitting.
// https://github.com/microsoft/TypeScript/issues/28884#issuecomment-503540848
...((passThroughComposedProps as unknown) as PassThroughComposedProps),
onClick: clickHandler,
} as ComposedProps;

return <ComposedComponent {...composedProps} />;
};

ModalLink.displayName = displayName;

return withRouter(ModalLink);
};

type Props = React.ComponentPropsWithoutRef<'button'> &
Required<Pick<React.ComponentPropsWithoutRef<'button'>, 'type'>>;

/**
* This one errors.
*/
declare const Button: React.FunctionComponent<Omit<Props, never>>;

/**
* This one works.
*/
// declare const Button: React.FunctionComponent<Props>;

const EnhancedButton = enhance(Button);

/**
* Type instantiation is excessively deep and possibly infinite.ts(2589).
*/
() => <EnhancedButton></EnhancedButton>;

Expected behavior:

I should get a proper error about missing properties (not the one about type instantiation):

Type '{}' is missing the following properties from type 'Readonly<Pick<OwnProps, "form" | "style" | "title" | "onClick" | "to" | "key" | "autoFocus" | "disabled" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | ... 252 more ... | "onTransitionEndCapture">>': to, type(2739)

Actual behavior:

I'm getting this:

Type instantiation is excessively deep and possibly infinite.ts(2589).

Playground Link:

Playground Link

Related Issues:

#32735

#34850