Skip to content

Maximum call stack size exceeded when emitting declaration file that should reference an unnameable infinite conditional type #44225

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

Closed
bluepichu opened this issue May 23, 2021 · 1 comment
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@bluepichu
Copy link

bluepichu commented May 23, 2021

Bug Report

πŸ”Ž Search Terms

maximum call stack size exceeded, declaration emit, unnameable, unnamable, unexported, infinite conditional type

πŸ•— Version & Regression Information

Crash on 4.2.4, 4.3.0-beta, 4.4.0-dev.20210523

⏯ Repo Link

https://github.com/bluepichu/typescript-issue-44225

(Can't use the playground since this requires multiple files.)

πŸ’» Code

// a.ts

type TupleIntersection<T extends unknown[]> =
	T extends [] ? unknown :
	T extends [infer Hd, ...infer Tl] ? Hd & TupleIntersection<Tl> :
	never;

export const intersectionCheck =
	<Types extends unknown[] = []>() =>
		<Intersection extends TupleIntersection<Types>>(obj: Intersection) => obj;

// b.ts

import { intersectionCheck } from "./a";

export const intersectionCheckWrapper =
	<Types extends unknown[] = []>() =>
		<Obj>(obj: Obj) => intersectionCheck<Types>()(obj);

Note: this only occurs with declaration emit enabled (since it's a crash in declaration emit), and only when TupleIntersection is not exported (see "workaround" below).

πŸ™ Actual behavior

Crash during declaration emit:

/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:88057
                throw e;
                ^

RangeError: Maximum call stack size exceeded
    at forEachSymbolTableInScope (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:38598:31)
    at getAccessibleSymbolChain (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:38617:20)
    at isAnySymbolAccessible (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:38727:45)
    at isSymbolAccessibleWorker (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:38770:30)
    at isTypeSymbolAccessible (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:38709:26)
    at typeToTypeNodeHelper (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:39169:26)
    at typeToTypeNodeHelper (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:39226:41)
    at mapToTypeNodes (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:39676:40)
    at typeToTypeNodeHelper (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:39186:37)
    at typeToTypeNodeOrCircularityElision (/Users/bluepichu/.config/yarn/global/node_modules/typescript/lib/tsc.js:39252:28)

πŸ™‚ Expected behavior

src/b.ts:5:49 - error TS2345: Argument of type 'Obj' is not assignable to parameter of type 'TupleIntersection<Types>'.

5   <Obj>(obj: Obj) => intersectionCheck<Types>()(obj);
                                                  ~~~


Found 1 error.

Notes and Workaround

If TupleIntersection is exported by a.ts, then you get the compile error as expected and no crash, even if b.ts doesn't explicitly import it. This is because, since a.ts is exporting TupleIntersection, it can be referenced in b.d.ts as import("./a").TupleIntersection.

I think the issue here is that declaration emit is trying to infinitely unroll the conditional type since it has no name for the type that it can reference. I'm not really sure what the compiler is supposed to do in this case though. (Maybe it should complain at the intersectionCheck declaration in a.ts that it's using a private name that needs to be exported?)

I think this is probably the same issue referenced by this comment on #42948, though the top-level issue there seems to have a different (though possibly related) cause.

@bluepichu bluepichu changed the title Maximum call stack size exceeded when emitting declaration file that should reference an unnamable infinite conditional type Maximum call stack size exceeded when emitting declaration file that should reference an unnameable infinite conditional type May 23, 2021
@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label May 27, 2021
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 4.4.0 milestone May 27, 2021
@andrewbranch andrewbranch added the Rescheduled This issue was previously scheduled to an earlier milestone label Aug 30, 2021
@weswigham
Copy link
Member

This no longer crashes and reports the error as expected. The declaration emit output is

export declare const intersectionCheckWrapper: <Types extends unknown[] = []>() => <Obj>(obj: Obj) => Types extends [] ? unknown : Types extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & (Tl extends [] ? unknown : Tl extends [infer Hd, ...infer Tl] ? Hd & any : never) : never) : never) : never) : never) : never) : never) : never) : never) : never) : never;

which isn't full fidelity (since that'd need inline type aliases), but 10 expansions is pretty OK.

@weswigham weswigham added the Fixed A PR has been merged for this issue label Jun 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
Development

No branches or pull requests

5 participants