Compiler missing "deep" type errors - 4.5.5 regression
See original GitHub issueBug Report
When dealing with a fairly large type produced by a generic, differences in types can lead to what should be compile-time errors being ignored. Example (see last // @ts-expect-error
).
🔎 Search Terms
A hard thing to search for, but I tried “deep” and “false negative” and didn’t see anything.
🕗 Version & Regression Information
- This changed between versions 4.4.4 and 4.5.5
- Still broken on current nightly
⏯ Playground Link
Playground link with relevant code
💻 Code
type DeepBrand<T> = T extends string | number | boolean | symbol | bigint | null | undefined | void
? {
t: 'primitive'
value: T
}
: T extends new (...args: any[]) => any
? {
t: 'constructor'
params: ConstructorParameters<T>
instance: DeepBrand<InstanceType<Extract<T, new (...args: any) => any>>>
}
: T extends (...args: infer P) => infer R // avoid functions with different params/return values matching
? {
t: 'function'
this: DeepBrand<ThisParameterType<T>>
params: DeepBrand<P>
return: DeepBrand<R>
}
: T extends any[]
? {
t: 'array'
items: {[K in keyof T]: DeepBrand<T[K]>}
}
: {
t: 'object'
properties: {[K in keyof T]: DeepBrand<T[K]>}
stringKeys: Extract<keyof T, string>
numberKeys: Extract<keyof T, number>
symbolKeys: Extract<keyof T, symbol>
}
// @ts-expect-error string vs void
const t1: DeepBrand<() => void> = {} as DeepBrand<() => string>
// @ts-expect-error string vs void
const t2: DeepBrand<() => () => void> = {} as DeepBrand<() => () => string>
// @ts-expect-error string vs void (should error, doesn't)
const t3: DeepBrand<() => () => () => void> = {} as DeepBrand<() => () => () => string>
🙁 Actual behavior
The compiler failed to noticed the difference between void
and string
, when it’s sufficiently “deep” in the expanded object.
🙂 Expected behavior
The compiler should have an error on the last line of the snippet.
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:10 (6 by maintainers)
Top Results From Across the Web
Improve recursion depth checks #46599 - GitHub
This PR improves relationship checking for recursive types in a number of ways: When ... Compiler missing "deep" type errors - 4.5.5 regression...
Read more >On Compiler Error Messages: What They Say and ... - Hindawi
Programmers often encounter cryptic compiler error messages that are difficult to understand and thus difficult to resolve.
Read more >Error for 'implicit function declaration' Warning in C
I always try to keep my source code free of compiler warnings. ... with that declaration, or that declaration is missing in the...
Read more >Finding and Analyzing Compiler Warning Defects - Ethz
Good compiler diagnostic warnings facilitate software development as they indicate likely programming mistakes or code smells. How- ever, due to compiler bugs, ...
Read more >CIS 1100 Compile Errors Walkthrough
There are two reasons that this error might occur. The first is that the ) character is indeed missing, and that there's some...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
The change between v4.4.4 and v4.5.5 occurred at bf6d164bd5b265ea9596e71b6468ecb695ebbb67.
The issue with the bisect was that the culprit commit was cherry-picked from main to release-4.5, and I only look at the timeline of commits going into main. I’m far from a git expert, but (warning: likely butchering terminology ahead)
git bisect
gets mad if you give it a pair likev4.4.4
andv4.5.5
because those tags exist on separate branches off of main that never reunite with main. To account for that, I actually run the bisect between themerge-base
of the respective inputs and main, so I’m actually bisecting between the point whererelease-4.4
andrelease-4.5
branched off of main. But in hindsight I think I only need to take the merge-base of the old ref. There still might be a problem if the behavior is different between the old ref and its merge base with main, though. I think that should be less common.The cause: #46974 / #46599
And FWIW, the bisect usually works, you just coincidentally only notice the ones that are particularly embarrassing 😛