-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Generic type unnarrowed by switch...case
#43873
Comments
Currently we don't contextually type the "argument" of an indexing element access expression - but you would only want to do that when the element access itself is contextually typed by a non-generic type the same way as described in #43183 |
I must have been staring at this for too long. This works fine: function createPrimitive(tagName: keyof typeof ElementTagNameMap) {
switch (tagName) {
case "a":
return function(): Element<"a"> {
return ElementTagNameMap[tagName]();
};
case "b":
case "c":
return function(): Element<"b" | "c"> {
return ElementTagNameMap[tagName]();
}; Although it is a bit redundant. |
Another case where I'm expecting something to be narrowed and it isn't: Surely there's a better way to write this than by explicitly reiterating the case clause in the type: function createPrimitive(tagName: keyof typeof ElementTagNameMap) {
switch (tagName) {
case "audio":
return function(attributes: ElementAttributesMap["audio"] = {}): Element<"audio"> {
// ^^^^^^^ ^^^^^^^
attributes.autoplay = true;
return ElementTagNameMap[tagName](attributes);
}; |
@DanielRosenwasser Are both of my problems related to the same "indexing element access expression" issue you described? Do you have any suggestions on how to better approach this? |
There are a bunch of problems here, only one of which is in-principle addressable as a novel thing:
|
Okay. People keep saying I have a bunch of problems but I'm blind to them so I'm going to see what I can do about figuring them out on my own in hopes of helping out the next guy. This is my current level of understanding when it comes to generics: https://ts.chibicode.com/generics/ Working off of this playground to start, I am using generics in 3 places:
Here's where things seem to be going awry: function createPrimitive<TagName extends keyof typeof ElementTagNameMap>(tagName: TagName) {
// Per @RyanCavanaugh's first bullet:
const tagNameImmutable = tagName;
switch (tagNameImmutable) {
case "a":
return function(attributes: ElementAttributesMap[TagName] = {}): Element<TagName> {
attributes.href = "whatever";
// [?] Shouldn't `attributes` get narrowed to just `AnchorElementAttributes`?
return ElementTagNameMap[tagName](attributes);
// [?] Shouldn't `() => Element<"a">` satisfy the constraint of `Element<TagName>`?
};
Problem 1:
Problem 2:
Problem 3: The compiler isn't currently designed to handle this:
|
I have resolved that this is the best way to handle my use case for now: case "a":
return function(attributes: ElementAttributesMap["a"] = {}): Element<"a"> {
attributes.href = "whatever";
return ElementTagNameMap[tagName](attributes) as Element<"a">;
}; and that this may improve in the future with #33014. |
Is there a more targeted issue for just this problem?
In case it helps, here's a simpler situation that demonstrates it without the other problems mentioned by @RyanCavanaugh: const stuff = {
string: '',
number: 0,
}
function f<T extends 'string' | 'number'>(x: T): void {
if (x === 'string') {
stuff[x].length // error :(
}
} |
Does Control Flow Analysis of Aliased Conditions help with this at all? |
I found a case that could be relevant: Playground link. I've confirmed that in this piece of code, |
Bug Report
🔎 Search Terms
🕗 Version & Regression Information
Theoretically this should be fixed by:
Similar issue:
I'm trying against the latest beta: 4.3.0-pr-43183-11 / 15fae38.
⏯ Playground Link
Playground link with relevant code
💻 Code
As a workaround I can assert
as Element<TagName>
on the inner-most return statement to silence the error.🙁 Actual behavior
🙂 Expected behavior
TagName
should be narrowed to one of the possible values dictated by the case clause.The text was updated successfully, but these errors were encountered: