Open
Description
- Node
v20.19.2
on mac - Works fine with
tsc
fromtypescript@5.5.4
- Errors visible with
@typescript/native-preview-darwin-arm64@7.0.0-dev.20250523.1
- Dependency chain
jest-environment-jsdom@29.7.0
@types/jsdom@20.0.1
@sinclair/typebox@0.27.8
npx tsgo src
node_modules/@sinclair/typebox/typebox.d.ts:137:63 - error TS2321: Excessive stack depth comparing types 'UnionToTuple<{ [K in T]: TLiteral<K>; }[T], UnionLast<{ [K in T]: TLiteral<K>; }[T]>>' and 'TSchema[]'.
137 export type TExcludeTemplateLiteralResult<T extends string> = TUnionResult<Assert<UnionToTuple<{
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
138 [K in T]: TLiteral<K>;
~~~~~~~~~~~~~~~~~~~~~~~~~~
139 }[T]>, TSchema[]>>;
~~~~~~~~~~~~~~~~~~
node_modules/@sinclair/typebox/typebox.d.ts:145:63 - error TS2321: Excessive stack depth comparing types 'UnionToTuple<{ [K in T]: TLiteral<K>; }[T], UnionLast<{ [K in T]: TLiteral<K>; }[T]>>' and 'TSchema[]'.
145 export type TExtractTemplateLiteralResult<T extends string> = TUnionResult<Assert<UnionToTuple<{
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
146 [K in T]: TLiteral<K>;
~~~~~~~~~~~~~~~~~~~~~~~~~~
147 }[T]>, TSchema[]>>;
~~~~~~~~~~~~~~~~~~
node_modules/@sinclair/typebox/typebox.d.ts:380:102 - error TS2321: Excessive stack depth comparing types 'UnionToTuple<{ [K in S]: TLiteral<K>; }[S], UnionLast<{ [K in S]: TLiteral<K>; }[S]>>' and 'TLiteral<TLiteralValue>[]'.
380 export type TUnionTemplateLiteral<T extends TTemplateLiteral, S extends string = Static<T>> = Ensure<TUnionResult<Assert<UnionToTuple<{
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
381 [K in S]: TLiteral<K>;
~~~~~~~~~~~~~~~~~~~~~~~~~~
382 }[S]>, TLiteral[]>>>;
~~~~~~~~~~~~~~~~~~~
node_modules/@types/jquery/misc.d.ts:7359:14 - error TS2717: Subsequent property declarations must have the same type. Property 'toStringTag' must be of type 'unique symbol', but here has type 'symbol'.
7359 readonly toStringTag: symbol;
~~~~~~~~~~~
node_modules/@typescript/native-preview-darwin-arm64/lib/lib.es2015.symbol.wellknown.d.ts:74:14 - 'toStringTag' was also declared here.
74 readonly toStringTag: unique symbol;
~~~~~~~~~~~
node_modules/@types/jsdom/base.d.ts:194:18 - error TS2411: Property 'Infinity' of type 'number' is not assignable to 'number' index type 'Window'.
194 readonly ["Infinity"]: number;
~~~~~~~~~~~~
node_modules/@types/jsdom/base.d.ts:195:18 - error TS2411: Property 'NaN' of type 'number' is not assignable to 'number' index type 'Window'.
195 readonly ["NaN"]: number;
~~~~~~~
Found 6 errors in 3 files.
Errors Files
3 node_modules/@sinclair/typebox/typebox.d.ts:137
1 node_modules/@types/jquery/misc.d.ts:7359
2 node_modules/@types/jsdom/base.d.ts:194
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
ahejlsberg commentedon May 28, 2025
Can you provide a short repro?
andyfleming commentedon May 29, 2025
Here's a minimal reproduction:
https://github.com/andyfleming/repro-for-typescript-go-929
Andarist commentedon Jun 5, 2025
@andyfleming u might have forgotten to push some files there
andyfleming commentedon Jun 5, 2025
@Andarist A fresh clone of that repository and running the commands in the README reproduces the errors for me.
Andarist commentedon Jun 6, 2025
That's not what it was asked for here. A short repro would be a self-isolated one, preferably within a single file. It shouldn't rely on massive external packages
sinclairzx81 commentedon Jun 10, 2025
@Andarist @jakebailey Hello,
I have just happened across this issue. As per request, I have setup a repro specifically for TypeBox at the link below:
https://github.com/sinclairzx81/typescript-go-issue-929
I should note that the referenced TypeBox version
0.27.8
is extremely out of date. The issue can be resolved by updating TypeBox to the latest0.34.33
. Unfortunately, there is a very long tail of downstream libraries and tools that do take a dependency on older versions of Jest (which in turn take the dependency to0.27.8
). Given the dependency chains downstream, it's not entirely trivial for applications to just update to the latest versions to leverage TS native.Happy to provide additional information if required.
S
Andarist commentedon Jun 10, 2025
The best thing you could provide is a self-isolated repro of the problem. This one still depends on an external library, one that has a lot of unrelated (to the problem) types in it. Investigating such repro takes considerably more time than investigating a small one.
sinclairzx81 commentedon Jun 10, 2025
@Andarist Project has been updated to include only offending types. Library dependencies have been removed as per request.
https://github.com/sinclairzx81/typescript-go-issue-929
Andarist commentedon Jun 10, 2025
This is great and way more actionable. Thanks ❤ I'll investigate this in the coming days
Andarist commentedon Jun 10, 2025
My preliminary findings...
This is a type ordering issue. The type arguments are being normalized and thus simplified.
getTrueTypeFromConditionalType
ingetSimplifiedConditionalType
leads to relating[...UnionToTuple<Exclude<{ [K in S]: TLiteral<K>; }[S], UnionLast<{ [K in S]: TLiteral<K>; }[S]>>, UnionLast<Exclude<{ [K in S]: TLiteral<K>; }[S], UnionLast<...>>>>, UnionLast<...>]
source toTLiteral<string>
.Here:
typescript-go/internal/checker/relater.go
Line 3779 in 9cf6764
We can observe:
And we enter
isRelatedTo
with their index info types:Buuut... in Corsa the order of this
originalSource
union is flipped. This ends up ineachTypeRelatedToType
and the whole relation ends up returningTernary.False
(in Strada too) but in Corsa it relates against the first constituent, well, first. That leads to deep recursion when the constraint of this source gets related here:typescript-go/internal/checker/relater.go
Lines 3608 to 3609 in 9cf6764
We can observe there:
When the compiler hits it again those can be observed:
As we can see, the source side here just "grows" through recursive attempts at relating its constraint to the target.
So, in a sense, Strada was able to return early from this as it related a different source first. Note that all of this is just within the normalization/simplification of the source. It can't be simplified - but it has to relate types to check if it can or not. And that leads to the dreaded "Excessive stack depth comparing types"