microsoft / microsoft/TypeScript
Needless evaluation of placeholder type when checking that an interface matches a constraint
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.4k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
Bug Report
🔎 Search Terms
type constraint, interface, evaluation, type checker, placeholder type
🕗 Version & Regression Information
This is the behavior in every version I tried, and I reviewed the FAQ for entries about this
⏯ Playground Link
Playground link with relevant code
💻 Code
Note: the utility type Zeros is designed to infinitely recur when it is fed unknown in order to exhibit the problem.
type Zeros<N, R extends unknown[] = []> =
N extends R['length'] ? R : Zeros<N, [0, ...R]>;
interface $Zeros { 0: unknown; type: Zeros<this[0]>; }
type apply$Zeros = apply<$Zeros, [3]>;
// ~~~~~~~~~~~~~~~~~~
// Type instantiation is excessively deep and possibly infinite
type apply<$T extends { type: unknown }, Args> = ($T & Args)['type'];
Alternate implementations of apply which don't reproduce the error can be found bellow:
// no type constraint
type apply<$T, Args> = ($T & Args)['type' & keyof $T];
// type constraint cheking keyof
type apply<$T extends (keyof $T extends keyof Type ? unknown : never), Args> =
($T & Args)['type' & keyof $T];
🙁 Actual behavior
It is my understanding that the type constraint $T extends { type: unknown } causes the type checker to evaluate Zeros<this[0]> as Zeros<unknown>, which leads to infinite recursion.
I believe this evaluation was not necessary because every type extends unknown, including undefined or never (an optional type field could also be caught without having to evaluate the value), therefore I consider that $T extends { type: unknown } could only check that the type key exists in $T without relaxing type safety.
I imagine that skipping this evaluation would also improve performance.
The alternative type safe solution of manually checking the existence of the keys is not user friendly.
🙂 Expected behavior
$T extends { type: unknown } should only check that the type field exists and enable to index $T & Args with type with no unexpected side-effect.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the linked Playground example and compare it with the two alternate apply implementations in the issue. The payload names no TypeScript source file or test, so tracing the type-checker constraint evaluation will require repository familiarity. Done means the constraint accepts the intended type without evaluating the recursive placeholder and existing type-safety behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100