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

TS2589: Type instantiation is excessively deep and possibly infinite #157

Open
MichaelJLiu opened this issue Apr 19, 2020 · 4 comments
Open

Comments

@MichaelJLiu
Copy link

After upgrading from TypeScript 3.5 to 3.8, I started getting error TS2589 on code that calls update with a Spec parameter. Here's a repro:

import update, { Spec } from "immutability-helper";

interface Widget {
	name: string;
}

function f(widget: Widget, spec: Spec<Widget>): Widget {
	return update(widget, spec); // <== TS2589
}

Compiler output:

repro.ts:8:9 - error TS2589: Type instantiation is excessively deep and possibly infinite.

8  return update(widget, spec);
          ~~~~~~~~~~~~~~~~~~~~

The error seems to occur only when strict null checks are enabled.

Is there something wrong with my code? Or is this a new limitation of the TypeScript compiler?

@kolodny
Copy link
Owner

kolodny commented Apr 23, 2020

Is this the same as #150?

@MichaelJLiu
Copy link
Author

As suggested in #150, adding an explicit type argument resolves the problem:

return update<Widget>(widget, spec); // no more TS2589

Does anyone know why recent versions of TypeScript can no longer infer the type?

@kolodny
Copy link
Owner

kolodny commented Apr 23, 2020

I think I understand what's happening. Usually when you pass in a spec object, it resolves to a spec and doesn't need to keep what the spec can be open ended. The issue is when you try to type that arg as a spec there's a recursive definition of Spec.

This also shows up when trying to just type that arg as Spec

update(1, {$set: 2}); // ok
update(1, {$set: 2} as Spec<any>); // Type instantiation is excessively deep and possibly

This was probably an issue in previous TS version, however, I believe it was more permissive on issues like that and didn't consider them an error

@MichaelJLiu
Copy link
Author

immutability-helper/index.d.ts declares update as follows:

declare const _default: <T, C extends CustomCommands<object> = never>(object: T, $spec: Spec<T, C>) => T;
export default _default;

If I call update with arguments of type Widget and Spec<Widget>, I don't understand why TypeScript can't immediately infer that T is Widget.

But in any case, can anything be done to avoid having to specify an explicit type argument, either in immutability-helper or in the TypeScript compiler? Or should this just be documented as a known limitation?

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

2 participants