-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Type parameter constraint not satisfied anymore since 5.1 #55743
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
Hmm, before 5.1 this was just a very complicated way of saying function f<
KEY extends string,
LEFT extends "leftValue1" | "leftValue2",
RIGHT extends "rightValue1" | "rightValue2"
>(key: KEY, left: LEFT, right: RIGHT): void; In other words, it was as if the type Pair<KEY extends string> = Literal["pairs"]; The We now defer resolution of the @martinhiller Is there a reason the types are written in this way, which seems overly complicated? Or is the repro distilled from something more complex where |
If I didnβt know any better I would think that
was an attempt to pick from a discriminated union (where |
It does, following #53098: type Choices = { key: "a", value: string } | { key: "b", value: number }
type Choose<K extends string> = (Choices & { key: K })["value"];
type TA = Choose<"a">; // string
type TB = Choose<"b">; // number
type TC = Choose<"c">; // never Previously, the resolved type would be |
@ahejlsberg Yes, you are correct that the type Literal =
| {
keyPart1: "key-1.1";
keyPart2: "key-1.2";
pairs:
| {
left: "leftValue-1.1";
right: "rightValue-1.1";
}
| {
left: "leftValue-1.2";
right: "rightValue-1.2";
};
}
| {
keyPart1: "key-2.1";
keyPart2: "key-2.2";
pairs:
| {
left: "leftValue-2.1";
right: "rightValue-2.1";
}
| {
left: "leftValue-2.2";
right: "rightValue-2.2";
};
}; So a more complete example (which better demonstrates our intention) is the following: To give you some more background: The What's also interesting (back to the simple example from the initial bug report): If we replace So instead of: declare function f<
KEY extends string,
LEFT extends Left<KEY>,
RIGHT extends Right<KEY, LEFT>,
>(key: KEY, left: LEFT, right: RIGHT): void; We can write: declare function f<
KEY extends string,
LEFT extends Left<KEY>,
RIGHT extends Right<KEY, Left<KEY>>,
>(key: KEY, left: LEFT, right: RIGHT): void; How can declare function f<
KEY extends string,
LEFT extends Left<KEY>,
RIGHT extends (Pair<KEY> & {
left: LEFT;
})["right"],
>(key: KEY, left: LEFT, right: RIGHT): void; I hope this is helpful. |
@martinhiller Thanks for the additional info. I'm quite certain the example didn't work as intended previously. With TS 5.0 or earlier, if you hover over function f<
KEY1 extends string,
KEY2 extends string,
LEFT extends "leftValue-1.1" | "leftValue-1.2" | "leftValue-2.1" | "leftValue-2.2",
RIGHT extends "rightValue-1.1" | "rightValue-1.2" | "rightValue-2.1" | "rightValue-2.2"
>(key1: KEY1, key2: KEY2, left: LEFT, right: RIGHT): void In other words, the f("foo", "bar", "leftValue-1.1", "rightValue-2.2"); In T.S 5.1 and later we appropriately defer resolution of the types. Hovering over function f<
KEY1 extends string,
KEY2 extends string,
LEFT extends Left<KEY1, KEY2>,
RIGHT extends Right<KEY1, KEY2, LEFT>
>(key1: KEY1, key2: KEY2, left: LEFT, right: RIGHT): void This means that That said, you're getting an error because the checker can't prove that Not sure I can help beyond that since I don't 100% understand what you're trying to accomplish. |
@ahejlsberg Thank you very much for taking the time to respond in such detail! You are correct that while TS < 5.1 does not report an error in the function declaration, you are indeed able to pass invalid left/right value combinations. In that regard, deferring the type resolution already improved the situation. The ultimate goal of this demo scenario is that users can only invoke function Content assist for Content assist for It seems we can get around the reported error by replacing the constraint for type Right<
KEY1 extends string,
KEY2 extends string,
LEFT extends string,
> = (Pair<KEY1, KEY2> & {
left: LEFT;
})["right"]; Given that this scenario did not fully work as intended in pre 5.1, and that "reducing" |
π Search Terms
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play?#code/C4TwDgpgBAMglsCAnAhgGygXigbwLABQUUA1hCAFxQBEA0gKICa1A3IcWCnEgM4XvEoAH1wDBgtBABmwKtUkyAaugCuEAIysx4qEjgBzABayaeo8GVo1mtkR0BfbSPx2dUBSfnSLqiACYtVx0zYzkQnyt-QLd7W1jCQlBIKAAFLiQAHgZGKAgAD0QAOwATHigeYD1C-QA+LCgACnhEVAwAMlE7MkoobLiASgBtak5uHmoAXVtE8GgYbyymXIKIErKKqtr6tO5Fxhrhj0npgiToACUDYz3lotLyyrhqgBpYegAxABVb1fv5mT2NTq2AaO0y2TqHRcxA8VBgH0+A2G4WOCQIxQgAGM0CgkNApCpCpjgHAAPaFKBSDICbI-NYPTbPATwr50v4LCFMuznACSAHEABLffJ3MqXcx7V4sz41Lk1BrdKjZV6wt5fV7hKi8wWffpUABupLgxVsQA
π» Code
π Actual behavior
On line 27 (second to last line), the usage of type
LEFT
is marked with an error:π Expected behavior
The provided type definition should be considered correct.
Type argument
LEFT
is constrained byLeft<KEY>
, which is exactly the constraint imposed by theRight
type.Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: