-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Type narrowing not working for unions of tuples with object literals #31613
Comments
Hi guys, not sure if this helps but here's another example which I believe to be the same issue: type FieldArray = string[]
type FieldSet = Record<string, any>
type FieldParams =
| [ FieldArray, FieldSet ]
| [ FieldArray ]
| [ FieldSet ]
function convertFieldParams (fields: FieldParams): Field[] {
const normalised = typeof fields[1] === 'undefined'
? fields[0] instanceof Array
? [ fields[0], {} ]
: [ [], fields[0] ]
: fields
// ...
} I would expect the normalised variable to have a type of I found a workaround by doing this: const normalised: [ FieldArray, FieldSet ] =
fields.length === 1
? fields[0] instanceof Array
? [ fields[0], {} ]
: [ [], fields[0] ]
: fields |
Any update? Fixing this issue would make tuples much more powerful :-) |
Probably same as #12849
So narrowing directly on the tuple type works fine, but when destructuring or assigning to an intermediate variable, it does not narrow correctly. |
@GeeWee: I think that those are effectively two separate bugs, as the issue describes type narrowing without destructuring on tuples with primitive (working) and non-primitive (not working) values. |
I think you're probably right actually. |
Looks like this is probably a bug in |
I'd like to try this if no one started work |
Sounds good, I wasn't planning to start on it until after the beta starts. |
This is actually not specific to tuples. Control-flow narrowing doesn't work with any nested properties: interface A { data: "a" }
interface B { data: "b" }
interface C { data: "c" }
type Y = { a:A, b:C } | { a:B, b:B }
function foo(y: Y) {
if (y.a.data === "b") {
return y.b.data === "c"
}
} It probably could be done but would require us to either (1) re-think handling of unions of object types or (2) how to relate entity-named discriminants that share a prefix. |
See open TS issue microsoft/TypeScript#31613 Marked with FIXME for when TS feature/bug fix lands upstream [This code will likely be removed in v17 prior to the feature landing, but may be retained within v16 for longer.] Similar code "works" at https://github.com/graphql/graphql-js/blob/1f8ba95c662118452bd969c6b26ba4e9050c55da/src/error/GraphQLError.ts#L47 because all the option properties are optional.
Possibly related: #48378 |
3 years old, still not fixed. Is this issue dead? It was first scheduled for 3.7 and then repeatedly rescheduled until it ended in the backlog. Fixing this would help in several use cases and greatly improve expressivity. I have several parts in my code base where I need to fall back to very generic types that are not helpful at all what could be a union of tuples. |
It's not possible to narrow unions of tuples with object literals
TypeScript Version: 3.4.5, 3.5.0-rc
Search Terms: tuple narrow object literals
Code:
Narrowing tuples with primitive types works as expected:
However, when the tuple contains object literals, narrowing doesn't work at all:
Expected behavior:
The object literal within the tuple is correctly narrowed down to type
B
Actual behavior:
The object literal is not narrowed, leaving it at type
C | B
.Playground Link: Link
Related Issues:
#26323
#24120
#10530
The text was updated successfully, but these errors were encountered: