Repository navigation
Type correlation regression #54834
Description
Bug Report
🔎 Search Terms
indexed Access Inference Improvements, indexed access type, mapped type, correlated types
🕗 Version & Regression Information
When did you start seeing this bug occur?
Without Readonly it never worked, the compiler doesn't see the correlation between v[node.type] and node.
With Readonly stopped working from 5.1.3.
⏯ Playground Link
With Readonly
Without Readonly
💻 Code
type NumericLiteral = {
value: number;
type: "NumericLiteral";
};
type StringLiteral = {
value: string;
type: "StringLiteral";
};
type Identifier = {
name: string;
type: "Identifier";
};
type CallExpression = {
name: string;
arguments: DropbearNode[];
type: "CallExpression";
};
type DropbearNode =
| NumericLiteral
| StringLiteral
| Identifier
| CallExpression;
type TypeMap = {
[K in DropbearNode["type"]]: Extract<DropbearNode, { type: K }>;
};
type Visitor = {
[K in keyof TypeMap]: (node: Readonly<TypeMap[K]>) => void;
// I am referring to this ^ one...
};
function visitNode<K extends keyof TypeMap>(
node: Readonly<TypeMap[K]>,
// ... and ^ this one
v: Visitor
) {
v[node.type](node);
}🙁 Actual behavior
The focus is the implementation of the visitNode function .
Without the use of Readonly in the definition of Visitor and visitNode the code does not compile in any version of TS. On the other hand, using Readonly in those definitions has worked until 5.1.3. Thanks to those Readonly TS was somehow able to see the correlation between v[node.type] and node.
P.S. It seems that v[node.type as K](node) always solves the problem, in all versions, with or without the use of Readonly.
🙂 Expected behavior
I repropose a simplified version of this example because I've recently had a chance to get my hands back on code that makes use of the pattern suggested in #47109. This is sort of a simplified version of what is suggested in that PR so I am not sure about the right behaviour.
It would be nice if TS would be able to support this simplified pattern for expressing correlations, instead of something more convoluted like this one where I think I am perfectly following what is indicated in #47109. And TS seems to be able to do it, although I don't know why Readonly was needed nor why it suddenly stopped working.
Activity
typescript-bot commentedon Jun 29, 2023
The change between origin/release-5.0 and origin/release-5.1 occurred at 9769421.
RyanCavanaugh commentedon Jun 29, 2023
#53098
Andarist commentedon Jun 30, 2023
So it seems that this fixes it #54689 but I'm not entirely sure if that solution is on the right track.
ahejlsberg commentedon Jul 31, 2023
I think this somewhat accidentally worked with
Readonly, but now we do a better job of preserving the higher order types and thus we detect more situations where types differ at higher order. A formulation of the problem that more closely follows the pattern in #47109 seems to work nicely:typescript-bot commentedon Aug 3, 2023
This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.
jfet97 commentedon Aug 3, 2023
Anders Hejlsberg (@ahejlsberg) yes that solution works nicely until we need to apply modifiers to the type of
nodejust likeReadonly. Is there a solution for this? Link to playgroundAndarist commentedon Jan 15, 2024
It works if
Readonlygets pushed intoDropbearNodeand if we avoid wrapping it over{ type: P }: TS playground.