-
Notifications
You must be signed in to change notification settings - Fork 12.8k
5.6 regression: Inference related regression: Wider covariant inference gets picked over more narrow contravariant one #59764
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
Comments
To be clear, this is a real builder error observed in Google that has been boiled down to a minimal reproduction with changed names. |
Confirmed that #59709 does not resolve this issue. |
This seems correct? Let's say you wrote this: interface Foo {
type: 'foo';
optionalProp?: boolean;
}
type Consumer<T> = (arg: T) => void;
declare function someFunc<T extends Foo>(consumer: Consumer<T>, defaultT: T): T;
declare const fooConsumer: Consumer<Foo>;
const result = someFunc(fooConsumer, { type: 'foo', extra: "bar" });
result.extra; // should be OK! |
So I have at least three more classes of similar regressions to this we're seeing in Google that I need to investigate and then create simplified repros. My Consumer name was bad. Here's the real code with names changed to make it a little less clear on what you might infer to be the correct behavior: function functionName<C extends SomeUnionOfTypes>(
arg1: Map<SomeType, AnotherType<YetAnotherType<C>>>,
arg2: C,
arg3: SomeType,
arg4: unknown,
): C Looking at this, it's less clear if we should prefer the literal type of The behavior has changed though which is causing new regressions. |
I was about to log a bug for this last largest class but, thinking about it more, I believe it boils down to this bug as well. Here's the example: declare class TestEnvironment<Args> {
constructor(template?: (args: Args) => Element, defaultTemplateData?: Args);
render(data?: Args): void;
}
declare function myElRender(data: MyRenderParams): Element;
type MyRenderParams = {
state: State,
optBool?: boolean,
};
enum State {
OPEN,
CLOSE,
}
const env = new TestEnvironment(myElRender, {state: State.OPEN});
function doTheRender({
state = State.OPEN,
optBool = false,
}: {state?: State, optBool?: boolean} = {}) {
env.render({state, optBool});
}
From the sample runs I performed, I detected 26 different tests failing this same way. This particular pattern impacts thousands of our tests in the Google codebase so is more important. If you feel this is significantly different, I can log a separate issue for this regression. |
declare class TestEnvironment<Args> {
constructor(template?: (args: Args) => Element, defaultTemplateData?: Args);
render(data?: Args): void;
}
declare function myElRender(data: MyRenderParams): Element;
type MyRenderParams = {
state: State,
optBool?: boolean,
};
enum State {
OPEN,
CLOSE,
}
function f1() {
const env = new TestEnvironment(myElRender, {state: State.OPEN});
// OK
env.render({ state: State.OPEN });
}
function f2() {
const env = new TestEnvironment(myElRender, {state: State.OPEN, optBool: true});
// optBool is required now??
env.render({ state: State.OPEN });
} This is a very good situation for using , defaultTemplateData?: NoInfer<Args> |
I understand that I can rewrite code to make it compile with the new inference changes. I'm not sure that we should have to though. My concern is that large swaths of pre-existing TypeScript is just going to stop compiling correctly around the world in this version. If that's okay, then okay. For this particular case on our end, it's a little tricky because the TestEnvironment class is written in JavaScript, not TypeScript. I need to test how much I can influence the generated type declarations in this case. |
Note that the title of this issue is a little bit misguided. Both of those types are inferred here internally. The fact that one of them was "named" was always irrelevant. It's all about the algorithm that chooses the covariant vs contravariant inference candidates to be selected as the final inferred type. |
I'm happy to change the title. Can you suggest a more accurate one? |
Wider covariant inference gets picked over more narrow contravariant one |
The available data we have is that this isn't going to be a disruptive change. The expected number of inference changes between versions isn't zero. The behavior change here is basically a "bug fix" in other contexts and it's expected to see similar-looking cases have similar-looking changes. |
OK. That's good to hear. I'm familiar with the tools to resolve these issues on our end ( Thanks for being patient with me as I log these regressions. Still getting a feel for this process :) |
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
π Search Terms
Inference
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play/?ts=5.6.1-rc#code/JYOwLgpgTgZghgYwgAgGIHt3IN4ChnJgCeADhAFzIDkMmVA3PsuiWMOiHADYAKULAfkoAjTFwhwQjAL65cxMsgDCHAM4BXALbQAPEwD0+5KGbqwyQ8gCqIBOk3bwoAOanzYABbBVyLqBQARDDAAB4QqgGEHijeGhAAdEwAKrgAfMgAvMgAFHBQzpRJAJSZ6QBu6MAAJoy4VRAIXHkoMOq2bBzIqvYQqG0IOikEECGQIFU+GFiWKg4QTiCu6GZR3r7+yEGh4ZGeMapxianZTHYgGtpQlCrnWrpJqQA0TPXw6lxgSYXPRYW19Y1msgzqpzLR0DcLtBrmo7lAdFNUvRkHIQeYoOF3uYst1tH1bNlwZC4Y8cAoKNRwVRpEVGJYCMgAHoCXBAA
π» Code
π Actual behavior
result
is of type{ type: "foo"; }
π Expected behavior
result
is of typeFoo
as it was in previous releasesAdditional information about the issue
See the comments in the example code for two tweaks to make for the code to work as expected. I get adding
in out
changing things. I'm less clear on why removing theextends
should make any difference.(Google note: relevant source location http://shortn/_eCS9djFiAR)
The text was updated successfully, but these errors were encountered: