Open karol-majewski opened 5 years ago
| ... 252 more ... |
That's a lot of properties ._.
@AnyhowStep That's correct. The component in question mixes-in the props defined by JSX.IntrinsicElements['button']
. There is a lot going on, and it is complicated, but it's a regression nonetheless because it worked in TypeScript 3.6.3.
We have the same issue in one of our larger projects. Works fine with 3.6.4 but not with 3.7.2
Using type keyof JSX.IntrinsicElements
Same issue, using keyof JSX.IntrinsicElements
type.
in src/compiler/checker.ts
on line 13208 (in v3.7.2) there is the following code:
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined {
if (!type || !mapper || mapper === identityMapper) {
return type;
}
if (instantiationDepth === 50 || instantiationCount >= 5000000) {
// We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
// with a combination of infinite generic types that perpetually generate new type identities. We stop
// the recursion here by yielding the error type.
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
return errorType;
}
instantiationCount++;
instantiationDepth++;
const result = instantiateTypeWorker(type, mapper);
instantiationDepth--;
return result;
}
So the value is hard-coded. Perhaps a configuration option to change this might be warranted. As a workaround for now, you could try upping this limit and rebuilding the compiler.
There have been proposals made to increase the limit. They've been rejected because it's seen as an "implementation detail" that should not be exposed.
PR: https://github.com/microsoft/TypeScript/pull/29602
Comment by @ahejlsberg
I'm very reluctant to expose the instantiation depth as a configurable parameter as it is an implementation detail that could change. Plus it is next to impossible to explain and reason about what value it should have.
https://github.com/microsoft/TypeScript/issues/29511#issuecomment-458620791
I agree with this part,
it is next to impossible to explain and reason about what value it should have.
If you're writing library code, you should not be messing with this limit. If you're writing application code and can force everyone on your team to use a hacked version of TS...
You can go ahead and hack the .js files for tsc and tsserver. Then, use https://www.npmjs.com/package/patch-package and commit the patch files
@Stianhn @rista404 Have you managed to reproduce this issue using a more reduced example? If what we're dealing with is a valid use case, then understanding it could help us come up with a heuristic for when type instantiation limit should not be applied.
I agree that messing with the internals leads nowhere — after all, you need to draw the boundary somewhere.
As far as I know, this limit is not something new. It existed before, yet somehow this code stopped working. I wonder what changed that directly influenced our use cases.
git bisect? =x
Can you grant @weswigham permission to the repository as well?
@DanielRosenwasser Yes! Invite sent @weswigham.
Another example in https://github.com/elastic/kibana/pull/47188/checks?check_run_id=303150613 where @timroes is trying to upgrade TS to 3.7.2:
x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts:58:10 - error TS2589: Type instantiation is excessively deep and possibly infinite.
58 return fetchAndTransformMetrics({
~~~~~~~~~~~~~~~~~~~~~~~~~~
59 setup,
~~~~~~~~~~
...
70 additionalFilters: [{ term: { [SERVICE_AGENT_NAME]: 'java' } }]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71 });
Related pull request: https://github.com/elastic/kibana/pull/47188
Related file: x-pack/legacy/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts
edit: this issue will be fixed with the aforementioned pull request. We've added an explicit intermediary type (https://github.com/elastic/kibana/pull/47188/commits/ef912fc12ab95bca7b117a66cadabecc84d9a16a) that resolves the issue for 3.7.
Worth noting that if you're upgrading from TS 3.5, something about how constraintDepth
works was changed that can cause the max depth error, for code that was previously working fine (and nesting 100+ layers deep).
https://github.com/microsoft/TypeScript/issues/33541
I'm bringing this up because it looks like @dgieselaar is migrating from TS 3.5
I also have a todo on my personal project to investigate this, https://github.com/AnyhowStep/tsql/issues/25
But I'm not focusing on TS 3.7 support yet
We have a similar issue with this code (roughly):
export type IconProps = TestProps & SizeProps & SpaceProps & DisplayProps & ColorProps<any>
// these are more than 450 props
export type ReactSvgProps = Omit<SVGProps<SVGSVGElement>, 'height' | 'width'>
export const createSvgIcon = (Component: FunctionComponent<ReactSvgProps>) => styled(Component)<IconProps>({display: 'inline-block', flex: '0 0 auto' }, compose(size, space, display, color))
// here we get the error
const MyIcon = createElement(Icon, { color: 'blue', marginRight: 'xs', marginLeft: '-xs' })
I have a similar issue with grommet-icons v4.4.0:
If I use the trash icon directly, all fine. If I wrap it with styled from styled component, I get the same message. No problem until typescript 3.5.2.
No Problem:
import { FormTrash } from 'grommet-icons';
export const AdProgramView = (props: PropType) => {
return (
<Container>
<h3>
{props.headline}
<FormTrash onClick={deleteIntentCallback} />
</h3>
</Container>
)
}
Problem with 3.7.2:
import { FormTrash } from 'grommet-icons';
const FormTrashStyled = styled(FormTrash)`
vertical-align: bottom;
cursor: pointer;
`
export const AdProgramView = (props: PropType) => {
return (
<Container>
<h3>
{props.headline}
<FormTrashStyled onClick={deleteIntentCallback} />
</h3>
</Container>
)
}
Same issue with styled components extending rmwc components:
import * as React from 'react'
import styled from 'styled-components'
import { Button } from '@rmwc/button'
const ButtonStyled = styled(Button)`
`
export function ConnectionSetting() {
return <React.Fragment>
<ButtonS />
</React.Fragment>
}
So what is the fix here. Nothing yet ? and we should not update to latest ts ? or refactor application code within limits ?
I've noticed that strict mode fixes it.
I just added "strict": true
to tsconfig.json
and it solved
I just added
"strict": true
totsconfig.json
and it solved
That does not solve it for me :/
I ran into this with xstate. The types work with 3.7.5 but upgrading to 3.8.2 gives error TS2589: Type instantiation is excessively deep and possibly infinite.
I made a quick gist to reproduce the issue, hope it helps: https://gist.github.com/qtiki/5f97233f609e516b5439e926514e85d9
Download the gist and run yarn
and yarn tsc
to get the error (or some npm
commands if you prefer).
Here is a small snippet that causes the issue. It is recursive but not using React.
export declare type NoMethods<T> = Pick<T, Exclude<{
[P in keyof T]: T[P] extends Function ? never : P;
}[keyof T], undefined>>;
export type PC<T, TChild=T> = {
[K in keyof NoMethods<TChild>]-?: PC<T, Exclude<TChild[K], undefined>>
} & {get(): string}
function test<T>(values: PC<T, unknown>[]): string[] {
return values.map(curr => curr.get()); //ERROR HERE
}
The strange thing is if I remove the map and change it to a forEach, this works fine. As in:
function test<T>(values: PC<T, unknown>[]): string[] {
const results: string[] = [];
values.forEach(curr => {
results.push(curr.get());
});
return results;
}
has no errors.
I'm getting it on the following snippet:
export class BaseConfig<T extends typeof BaseConfig> {
public constructor(private readonly environment: Pick<InstanceType<T>, keyof T>) {
// ...
}
}
I was attempting to get the public props as constructor arguments type.
Ran into the problem implementing a recursive mapper type:
export interface Route {
path: string;
label: string;
icon: React.ReactElement;
}
export type Routes = Record<string, Route>;
export interface NestedRoute extends Route {
children: NestedRoutes;
}
export type NestedRoutes = Record<string, NestedRoute>;
export type GetNestedRouteKey<R extends NestedRoutes> = {
[key in keyof R]:
| key
| keyof R[key]['children']
| GetNestedRouteKey<R[key]['children']>;
}[keyof R];
// * Example
type A = {
ideas: {
path: 'ideas';
label: 'Discover';
icon: ReactElement;
children: {
create: {
path: 'create';
label: 'Create';
icon: ReactElement;
children: {};
};
my: {
path: 'my';
label: 'My Ideas';
icon: ReactElement;
children: {
published: {
path: 'published';
label: 'Published';
icon: ReactElement;
children: {};
};
};
};
};
};
};
type B = GetNestedRouteKey<A>; // "ideas" | "create" | "my" | "published"
export type FlattenRoutes<R extends NestedRoutes> = Record<GetNestedRouteKey<R>, Route>; // Type instantiation is excessively deep and possibly infinite.
I get this issue right now but only in watch mode and only after file changes
Got the issue with the latest discord.js release (12.3.0) and ts-auto-mock (2.3.4). More details on the ts-auto-mock issue.
I have isolated an example of hitting this error when trying to provide types for a function that deals with async iterables. Error is only hit when the function implementation is available and replacing the implementation with a declaration removes the problem even though the types have to be instantiated all the same.
The recursive type looks like this.
type ZipResult<T extends unknown[], Result extends unknown[] = []> = {
0: ZipResult<Tail
The input array that instantiates this type is two elements long, so, perhaps naively, I would expect the recursion depth to be 6 (3 for recursion into ZipResult itself and 3 for recursion into Reverse). Nowhere near the limit of 50 mentioned earlier in the thread.
Code is available in the playground:
What's the likelihood of this issue getting addressed in the upcoming 4.2.0 release? Is someone actively working on this issue?
It seems the issue for us is that type aliases are not lazily evaluated, and the compiler tries to expand all combinations until it can't.
To work around this, we introduced an empty interface in places, as it seems they are lazy. It's a bit of a kludge, and also a bit awkward because interfaces can't be used in unions.
Is there a better workaround/approach that we can take today, or a change in the compiler/language that might help us?
I just hit this too when using 4.1's recursive conditional types. (Super amazing feature by the way.) It's hard to pair down to a simple example by the nature of this type of error. The below code allows someone to declare a TypeScript type. At the center of it all is Types
which is a recursive conditional type. I had to remove constraints on UnionType<Types>
to UnionType<unkown>
Further, there's other places in the code where I should be able to add constraints to Types
but I had to slowly remove them and add downcasts to prevent this error from showing up. Sorry, I know this is a lot of code, and doesn't repro with just the code below, but it is the level of complexity I'm dealing with. Using this code, it repros in the rest of my code.
export interface Type<T> {
kind: T,
}
export const str: Type<'string'> = { kind: 'string', };
export const num: Type<'number'> = { kind: 'number', };
export const bool: Type<'boolean'> = { kind: 'boolean', };
export const bigint: Type<'bigint'> = { kind: 'bigint', };
export const nul: Type<'null'> = { kind: 'null', };
export const undef: Type<'undefined'> = { kind: 'undefined', };
export interface LiteralType<TLiteralValue> extends Type<'literal'> {
kind: 'literal',
literal: TLiteralValue
}
export interface ArrayType<TElement> extends Type<'array'> {
kind: 'array',
elementType: TElement
}
export interface UnionType<TMembers> extends Type<'union'> {
kind: 'union',
memberTypes: Array<TMembers>
}
export interface ObjType<TShapeDefinition> extends Type<'object'> {
kind: 'object',
shapeDefinition: TShapeDefinition;
}
export const literal = <T>(stringLiteral: StringLiteral<T>): LiteralType<T> => ({
kind: 'literal',
literal: stringLiteral,
});
export const array = <T extends Types>(element: T): ArrayType<T> => ({
kind: 'array',
elementType: element,
});
export function obj<TShapeDefinition extends IShapeDefinition>(shapeDefinition: TShapeDefinition): ObjType<TShapeDefinition> {
return {
kind: 'object',
shapeDefinition
};
}
export type OptionalType<T> = UnionType<T | typeof undef>;
//TODO: UnionType should be able to be UnionType<Types> but there is a depth hueristic that blows up.
// That means functions and types have to cast until it's fixed
// https://github.com/microsoft/TypeScript/issues/34933
export type Types =
Type<'string'> |
Type<'number'> |
Type<'boolean'> |
Type<'bigint'> |
Type<'null'> |
Type<'undefined'> |
LiteralType<unknown> |
ArrayType<Types> |
UnionType<Types> | //Should be able to be UnionType<Types>, but has to be UnionType<unknown> to avoid this error!
ObjType<IShapeDefinition>;
export interface IShapeDefinition {
[index: string]: Types
}
export type Shape<TDefinition> =
TDefinition extends LiteralType<infer LiteralKind>
? LiteralKind
: TDefinition extends Type<'string'>
? string
: TDefinition extends Type<'number'>
? number
: TDefinition extends Type<'boolean'>
? boolean
: TDefinition extends Type<'bigint'>
? bigint
: TDefinition extends Type<'null'>
? null
: TDefinition extends Type<'undefined'>
? undefined
: TDefinition extends ArrayType<infer ElementKind>
? Array<Shape<ElementKind>>
: TDefinition extends UnionType<infer KeyKind>
? Shape<KeyKind>
: TDefinition extends ObjType<infer TShapeDefinition>
? { [P in keyof TShapeDefinition]: Shape<TShapeDefinition[P]> }
: never;
type ShapeDefinitionDistribute<TsType> =
TsType extends StringLiteral<TsType>
? LiteralType<TsType>
: TsType extends string
? Type<'string'>
: TsType extends number
? Type<'number'>
: TsType extends boolean
? Type<'boolean'>
: TsType extends bigint
? Type<'bigint'>
: TsType extends null
? Type<'null'>
: TsType extends undefined
? Type<'undefined'>
: TsType extends Array<infer TElementType>
? ArrayType<ShapeDefinition<TElementType>>
: TsType extends object
? ObjType<{ [P in keyof TsType]: ShapeDefinition<TsType[P]> }>
: never;
export type ShapeDefinition<TsType> =
NotAUnion<TsType> extends never
? UnionType<ShapeDefinitionDistribute<TsType>>
: ShapeDefinitionDistribute<TsType>;
//mad science: https://stackoverflow.com/questions/50639496/is-there-a-way-to-prevent-union-types-in-typescript
export type NotAUnion<T, U = T> = U extends any ? [T] extends [boolean] ? T : [T] extends [U] ? T : never : never;
export type StringLiteral<T> = T extends `${string & T}` ? T : never;
export type FlattenedUnion<T> =
T extends UnionType<infer K>
? FlattenedUnion<K>
: T;
export type CollapseSingleMemberUnion<T> =
NotAUnion<T> extends never
? UnionType<T>
: T;
export const flattenMembers = <T extends Types[]>(members: T): Array<FlattenedUnion<T>> => {
return {} as any as Array<FlattenedUnion<T>>; //code removed for this example
};
export const union = <T extends Types[]>(members: T): CollapseSingleMemberUnion<FlattenedUnion<T>> => {
const flat = flattenMembers(members); //Blows up sometimes
return {} as CollapseSingleMemberUnion<FlattenedUnion<T>>; // edited for this example
};
const blowsUpSomeTypes = union([obj({name: str, age: num}), obj({isSomething: bool, anotherValue: num})]);
just hit this error when trying to make a generic interface for an api that uses only post request. that api has a ton of request variations. I guess that did the thing :/ I hit the limit after only 17 requests(51 if I include all possible request param combinations).
Found this comment in src/compiler/checker.ts
function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
let result;
let extraTypes: Type[] | undefined;
// We loop here for an immediately nested conditional type in the false position, effectively treating
// types of the form 'A extends B ? X : C extends D ? Y : E extends F ? Z : ...' as a single construct for
// purposes of resolution. This means such types aren't subject to the instatiation depth limiter.
/*....*/
}
I removed as many intermediate templates as possible, and it started to help. Though, it's probably just kicking the can down the road and it greatly hurt readability as I have to put all my type mappings inline:
type ToDefinitionType<TsType> =
/*...*/
ObjType<{
[P in keyof TsType]-?: Prop<
ToDefinitionType<Exclude<TsType[P], undefined>>, //recursive
P extends {
[KK in keyof TsType]-?: undefined extends TsType[KK] ? KK : never
}[keyof TsType] ? true : false, false>
}>
I hav two mongoose type definitions A and B. Both are identical, except field types (e.g. number in A, string in B, only primitive types differ). A compiles fine, B throws this 'Type instantiation is excessively deep and possibly infinite.' :DDDDDDDDDDDD
Hilarious compiler.
I'm using a parser combinator to combine generic parser functions into more complex parsers. As soon as my parser expressions exceed a certain length (which I don't find excessive), this error occurs, forcing me to re-design my parsers.
The frustrating aspect about this is that the error message gives no indication of where it sees excessive complexity, forcing me to use trial and error to fix the problem.
I'd be happy to supply repro code if it helps.
just hit this error when trying to make a generic interface for an api that uses only post request. that api has a ton of request variations. I guess that did the thing :/ I hit the limit after only 17 requests(51 if I include all possible request param combinations).
For this particular use case i wouldn't use a generic interface but instead type the body as unknown
and then using a type assertion for each variation. You could abstract out some of the shared assertion logic (and corresponding types) to make it less verbose.
Would this work for you or is there a reason that a Generic would be better?
Just hit this problem when using createSlice in @reduxjs/toolkit.
I was able to distill it to a stand-alone typescript file:
declare type Draft<T> = WritableDraft<T>;
declare type WritableDraft<T> = {
-readonly [K in keyof T]: Draft<T[K]>;
};
declare type SliceCaseReducers<State> = {
[K: string]: (state: Draft<State>) => State;
};
function x<CaseReducers extends SliceCaseReducers<{ test?: classWithRecursiveType[]; }>>(what: CaseReducers) {
}
x<{
addComment: (state: WritableDraft<{
test?: classWithRecursiveType[];
}>) => {
test: WritableDraft<classWithRecursiveType>[];
};
}>({} as any);
declare type RecursiveType = string | RecursiveType[];
class classWithRecursiveType {
b: string;
a: RecursiveType; //comment me out to prevent the error
}
In this code, I'm getting an error for the line that starts with "x<{..." Type instantiation is excessively deep and possibly infinite.ts(2589)
If I comment out the line that starts with "a:..." the error stops.
@noam-honig
declare type RecursiveType = string | RecursiveType[];
Can you do this kinda of stuff in ts? ... that actually seems like a valid error to me.
That aside... our pipeline just suddenly started throwing this. The code changes between when it worked and stopped working is extremely minimal and leads me to believe a package update has caused it. Our usage of TS is light and (since we dont know TS that well) have not done a lot of crazy extending, generics or whatnots.
Oh.. and it compiles fine for me locally inside our docker container (im on windows).. but for my co-workers and our pipeline on unix.. the build fails (also inside the same container)
Yes you can, it was added sometime ago
On Tue, Jun 29, 2021 at 20:31 Nathan Alberg @.***> wrote:
@noam-honig https://github.com/noam-honig
declare type RecursiveType = string | RecursiveType[]; Can you do this kinda of stuff in ts? ... that actually seems like a valid error to me.
That aside... our pipeline just suddenly started throwing this. The code changes between when it worked and stopped working is extremely minimal and leads me to believe a package update has caused it. Our usage of TS is light and (since we dont know TS that well) have not done a lot of crazy extending, generics or whatnots.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/microsoft/TypeScript/issues/34933#issuecomment-870784541, or unsubscribe https://github.com/notifications/unsubscribe-auth/AD65PUYGICZOLTV6DKW5EWTTVH7PPANCNFSM4JJNCEHA .
So to anyone who lands here and is getting this error in Node with express.
Our pipeline suddenly broke. No major code changes on our part.. and it appears npm updated some packages
4.0.2
to 4.3.4
(i think)14.14.22
to 14.14.44
4.17.11
to 4.17.12
4.17.19
to 4.17.22
Running npx tsc
was after these updates was causing the deep and infinite
error. And very strangely..
for instance:
const router = express.router();
router.get('/v3/app/userOpportunities/:userOpportunity_id/roadmaps', [...]); // <-- this was one of the error lines
export { router }
and even more odd.... is that this STILL throws the error
...
router.get(':userOpportunity_id'); // still an error
...
and so I started playing around:
...
router.get(':userOpportunity'); // error
router.get('userOpportunity'); // no error (removed the semi colon)
router.get(':userOpp'); // no error changed word
having :userOpportunity
anywhere in my route was throwing the error. but userOpportunity
, :userOpp
, something else
etc would be fine.
I had three routes throwing errors.. all of them were acting similar but with different words.. 2 routes had :userOpportunity
it and the third was complaining about :recommendationId
This made me think that the express types were being naughty. I started rolling things back slowly. Thus, I added @type/express-serve-static-core
to my package.json (it was just a dependency) and forced it back to 4.17.21
and now the TS errors are gone.
On a side note.. this only seems to fail in a unix environment for some reason.
UPDATE looks like the package will get fixed soon: https://github.com/DefinitelyTyped/DefinitelyTyped/commit/6973d2cc7f0ac4601f449273e2b0ff8790fdcf72#r52861403
For what it's worth, I also hit this error when using @reduxjs/toolkit
, but specifically when using immer
in reducers in createSlice
et al.
@nawlbergs The new typings for express uses new TypeScript features in 4.0 to do wonders. See this line from its typings.
It's like constexpr
where we generate information from source, so we can get statically-typed req.params
from the path that we write. Unfortunately, these magic requires TypeScript compiler to do more work, and the TypeScript compiler at its current form cannot quite cope with it. This is the root cause of the problem.
Still, +1 for both TypeScript and Express/Typings team to make the world more type-safe.
Chimed in because I almost wasted with my own implementation, and also want to let more people know about this feature of TypeScript and how Express is not trying to be naughty, but more useful.
Hope this gets fixed soon.
@shanehsu
I agree, +1 to the typescript team and the team behind DefinitelyTyped. It's a huge boon to the JS community. Not a fan of weird bugs that make no sense to me and break our entire app however :P
This made me think that the express types were being naughty. I started rolling things back slowly. Thus, I added
@type/express-serve-static-core
to my package.json (it was just a dependency) and forced it back to4.17.21
and now the TS errors are gone.
Thanks for the tip. I installed and setup https://github.com/rogeriochaves/npm-force-resolutions and added this to package.json
:
"resolutions": {
"@types/express-serve-static-core": "4.17.21"
}
After a npm install
the issue is resolved.
I hope to adjust the limit by tsconfig. How do you think?
@nawlbergs thank you!
I was using :orderReferenceNumber
in tsoa
and it was breaking, but changing it to :orderReference
fixed my issue :)
Currently, the limitation thresholds are hard-coded, to 50
and 5000000
.
src/compiler/checker.ts
if (
instantiationDepth === 50 ||
instantiationCount >= 5000000
) {
// We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
// with a combination of infinite generic types that perpetually generate new type identities. We stop
// the recursion here by yielding the error type.
error(
currentNode,
Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite
);
return errorType;
}
To make this configurable, I pushed a PR #44997, which makes those values be able to be set by compilerOptions
that can be passed through CLI options or tsconfig.json
, like an example below.
{
"compilerOptions": {
"instantiationDepthLimit": 100,
"instantiationCountLimit": 10000000
}
}
Though the PR is incomplete, just showing your interest would make its priority higher.
Thanks.
in the meantime, one can use patch-package to create a per-project patch to implement the temporary fix:
edit node_modules/typescript/lib/tsc.js
: search for 5000000
or instantiationCount
and increate both the instantiationDepth
and instantiationCount
limits
run node_modules/.bin/patch-package typescript
(via yarn patch-package typescript
or npx patch-package typescript
to generate the patch
should end up something like this in the patches/
folder:
diff --git a/node_modules/typescript/lib/tsc.js b/node_modules/typescript/lib/tsc.js
index 78c5ec2..7d6c586 100644
--- a/node_modules/typescript/lib/tsc.js
+++ b/node_modules/typescript/lib/tsc.js
@@ -49264,7 +49265,7 @@ var ts;
if (!couldContainTypeVariables(type)) {
return type;
}
- if (instantiationDepth === 50 || instantiationCount >= 5000000) {
+ if (instantiationDepth === (50 * 2) || instantiationCount >= (5000000 * 2)) {
ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("checkTypes", "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth: instantiationDepth, instantiationCount: instantiationCount });
error(currentNode, ts.Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
return errorType;
make sure to always apply the patch (e.g. after installation) by following patch-package's docs for this purpose (also note this).
if using typescript project references, beware of hoisting of typescript itself - it didn't work for me and resolved to some random package's typescript install - do this in the root package.json
(the nohoist
):
{
"name": "...",
"workspaces": {
"packages": [
"...",
"..."
],
"nohoist": [
"typescript",
"typescript/**"
]
},
Note: after some testing, it seems there's no value that's enough at least for my use case, even though it is not infinitely recursive...
P.S. If a project is using something like babel-loader
through webpack (e.g. CRA), I do not know how to configure the tsc executable there or whatever other changes would be needed.
If someone finds this - please let me know.
I getting this error in an absurd way in server-side express based app:
app.get('/api/cms/:module/listing/:category', detectContentModule, loadContentPublicListingPage);
works, but
app.get('/api/cms/:module/listing/:categoryUrlName', detectContentModule, loadContentPublicListingPage);
ends up with firing this TS2589: Type instantiation is excessively deep and possibly infinite.
error.
The rest of code is the same.
Note: TS 4.3.5 suffers this. Migrated to 4.4.3 with no effect. Project is mix of TS and JS (transition to TS is in progress).
ts config is following:
{
"compilerOptions": {
"experimentalDecorators": true,
"module": "commonjs",
"target": "ES2018",
"lib": ["es2018"],
"allowJs": true,
"moduleResolution": "node",
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"noEmitOnError": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true
},
"exclude": ["node_modules", "./dist"],
"include": ["./src/**/*"]
}
@koteisaev See my comments above. Its an issue with the @type/express-serve-static-core
TypeScript team - is there any thought of putting in some syntax that could help guide the compiler during inference beyond a heuristic? For libraries that do schema translation this is going to be a continual headache. Perhaps something like a resolve
keyword to tell the compiler to fully compute a type resolution, cache it and from then on treat the type as if it were declared by the user explicitly? Is the compiler already doing this as it's resolving types?
// This is a fully resolved type that the compiler knows the user really really wants to happen so go nuts and cache it
type ResolvedType = resolve DeeplyRecursiveType<string, Person>
//This also gives a caching point for each type it is given;
type MySchemaMapper<T> = resolve DeeplyRecursiveType<string, T>
//Using the above case this:
type MappedPerson = MySchemaMapper<string, Person>
//is equivalent to this:
type MappedPerson = resolve DeeplyRecursiveType<string, Person>
Intellisense could also benefit from this as a lot of mapped types end up being unreadable as they show complicated expansions. If the resolve
keyword were used, intellisense could display the simplest form of the type declaration and not continue expanding when it encounters a "resolved type." From my experience these deeply recursive types coincide with very generic API boundaries 90% of the time, so it's a natural fit.
All type instantiations are already cached.
TypeScript Version: 3.7.2, 3.8.0-dev.20191102 (worked in 3.6)
Search Terms:
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
and3.8.0-dev.20191102
. It worked correctly with3.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:
it works again despite the fact
Omit<Props, never>
should be the same as justProps
.Source code
```ts 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 isDefinedExpected behavior:
I should get a proper error about missing properties (not the one about type instantiation):
Actual behavior:
I'm getting this:
Playground Link:
Playground Link
Related Issues:
32735
34850