json-schema-to-ts
json-schema-to-ts copied to clipboard
Error: Excessive stack depth comparing types 'ParseMixedSchema<?, T>' and 'ParseMixedSchema<?, T>'.ts(2321)
As of version 1.6.5, I now get this error in several places in my code.
Excessive stack depth comparing types 'ParseMixedSchema<?, T>' and 'ParseMixedSchema<?, T>'.ts(2321)
It comes from this:
import type { FromSchema } from 'json-schema-to-ts';
import createHttpError, { NamedConstructors } from 'http-errors';
import { URLSearchParams } from 'url';
export type ValidatedAPIGatewayProxyEvent<S> = APIGatewayProxyEvent &
FromSchema<S>;
which I adopted from the Serverless Framework TS template.
I create a JS/JSON API Gateway schema, e.g.:
const schema = {
type: 'object',
properties: {
body: {
type: 'object',
properties: {
coupon_id: { type: 'string' },
end_of_term: { type: 'boolean' },
plan_id: { type: 'string' },
subscription_id: { type: 'string' },
reactivate: { type: 'boolean' },
first_payment: { type: 'boolean' },
},
required: ['end_of_term', 'plan_id', 'subscription_id'],
additionalProperties: false,
},
},
} as const;
and pass it to Sentry's wrapHandler
:
export const handler = Sentry.AWSLambda.wrapHandler<
ValidatedAPIGatewayProxyEvent<S>,
APIGatewayProxyResult | undefined
>(...
This has worked fine up until the latest release.
Hi @ffxsam and thanks for the issue.
Everything seems fine on json-schema-to-ts
side. It's the combination of Sentry and FromSchema
that seems to generate too many type computations 🤔 I don't even get why ParseMixedSchema<?, T>
is mentioned here, as your schema is not mixed (i.e. you do not provide an array of types
but simply "object"
).
Can you try defining ValidatedAPIGatewayProxyEvent<S>
in a separate type ?
type Event = ValidatedAPIGatewayProxyEvent<S>
export const handler = Sentry.AWSLambda.wrapHandler<
Event,
APIGatewayProxyResult | undefined
>(...
...or simply, not providing explicitely the generic types to wrapHandler
? (they can be inferred from the handler
itself, I think)
const yourFunc = async (event: ValidatedAPIGatewayProxyEvent<S>) : Promise<APIGatewayProxyResult | undefined> => ...
export const handler = Sentry.AWSLambda.wrapHandler(yourFunc)
What version of json-schema-to-ts
did you use before having the error ? Was json-schema-to-ts
the only library that you upgraded or did you upgrade Typescript as well ?
Hey @ThomasAribart, thanks for the reply!
You'll have to excuse me, as my TypeScript ability is passable at best.
type Event = ValidatedAPIGatewayProxyEvent<S>;
This results in an error, Cannot find name 'S'
.
Unfortunately, I can't rely on implicit types here. The code for wrapApiHandler
is more complex than illustrated here (it took me hours to figure out). I can post it in its entirety if that helps you.
TypeScript was updated, but I reverted it step by step back to version 4.5.2 and the issue still persisted. Then I reverted from json-schema-to-ts
version 1.6.5 to 1.6.4 and that resolved it.
S
is supposed to be the type of your schema, defined with the as const
statement:
import { schema } from './schema'
type S = typeof schema
Thanks, Thomas! I appreciate the help, but unfortunately, I don't have the bandwidth to try to track down what's going on. I'm guessing it's due to some sloppy TypeScript that json-schema-to-ts
was previously more forgiving about. I'll pin my project to version 1.6.4 and call it a wrap.
I've been seein the same error in the latest version in https://github.com/feathersjs/feathers/tree/dove/packages/schema. The smallest example I could come up with to reproduce looks like this:
class Test<S extends JSONSchema> {
readonly type: FromSchema<S>;
}
const schemaA = {
type: 'object',
additionalProperties: false,
properties: {
name: { type: 'string' }
}
} as const;
const schemaB = {
type: 'object',
additionalProperties: false,
properties: {
name: { type: 'string' }
}
} as const;
const t: Test<typeof schemaB> = new Test<typeof schemaA>();
Maybe that helps, I can try and do some more digging if you think it's worth investigating. Either way, this is a great project!
Oop, I made a duplicate issue here: https://github.com/ThomasAribart/json-schema-to-ts/issues/56
Filed here because I haven't seen this error on any other codebases aside from when I use json-schema-to-ts
But now I'm thinking we have exposed some bug in TypeScript.
Typescript 4.7, which introduced variance annotations, has been released. I believe variance annotations could help solve this issue. And overall speed up type inference. @ThomasAribart, could you please look into that?
@daffl @psznm @ffxsam @ericvicenti Indeed, it seems like the variance annotation helps a bit. The smallest example you provided is fixed by declaring S
as invariant
(i.e. with both in
and out
annotation).
I guess it skips the FromSchema
type computation altogether and call it a day if schemaA
and schemaB
are equal (or not):
class Test<in out S extends JSONSchema> {
readonly type?: FromSchema<S>;
}
const schemaA = {
type: "object",
additionalProperties: false,
properties: {
name: { type: "string" },
},
} as const;
const schemaB = {
type: "object",
additionalProperties: false,
properties: {
name: { type: "string" },
},
} as const;
// works fine
const test: Test<typeof schemaB> = new Test<typeof schemaA>();
However, I'm not completely sure this fixes the issue ? 🤔
I've found that defining the expected type as the default value of a second generic type is a functioning work-around though:
// "out" annotation is welcome but not necessary
class Test<S extends JSONSchema, out T = FromSchema<S>> {
readonly type?: T;
}
const schemaA = {
type: "object",
additionalProperties: false,
properties: {
name: { type: "string" },
},
// this time, you can have different specs between schemas
required: ['name']
} as const;
const schemaB = {
type: "object",
additionalProperties: false,
properties: {
name: { type: "string" },
},
} as const;
// works fine
const test: Test<typeof schemaB> = new Test<typeof schemaA>();
Can you confirm that it work ? Does it close this issue ?
I think this can be closed. I haven't seen this weirdo error in a while
Now I just need to find workarounds for "Type instantiation is excessively deep and possibly infinite" 😤