-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Nested generic object of unions is not assignable to equivalent union of nested generic objects #51318
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
In one case you have an object that can either store a or b, in the other case you either have an object that can only store a, or an object that can only store b. The types are not equivalent. Although the assignment of |
Perhaps this is a more motivating example. I'm basically trying to use a custom result type that tracks possible errors, a bit like Haskell's interface Success<T> {
ok: true
value: T
}
interface Failure<E> {
ok: false
error: E
}
type Result<T, E> = Success<T> | Failure<E>
const success = <T>(value: T): Success<T> => ({ok: true, value})
const failure = <E>(error: E): Failure<E> => ({ok: false, error})
declare function test<T, E>(fn: (value: unknown) => Result<T, E>): Result<T, E>
// This works, for whatever reason.
test((val) => {
if (typeof val !== "string") return failure("not a string" as const)
if (val.length === 0) return failure("empty string" as const)
return success(val)
})
// This doesn't work. Why is that?
test((val) => {
if (typeof val !== "string") return failure({code: "not a string"} as const)
if (val.length === 0) return failure({code: "empty string"} as const)
return success(val)
})
// With an explicit type annotation, everything is ok.
test((val): Result<string, {code: "not a string" | "empty string"}> => {
if (typeof val !== "string") return failure({code: "not a string"} as const)
if (val.length === 0) return failure({code: "empty string"} as const)
return success(val)
}) |
A few things to discuss. First, for types with a single value of their type parameter, indeed Second, in general, generic inference won't collect two disparate candidates and then infer to a union of them. This makes generics for the purposes of input validation largely useless, e.g. a call to something like The middle |
This issue has been marked as 'Not a Defect' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
Bug Report
π Search Terms
union, generic, nested, nested, complex
π Version & Regression Information
β― Playground Link
Playground link with relevant code
π» Code
π Actual behavior
The assignment
outer = inner
fails following errorπ Expected behavior
As far as I can tell, it should be accepted, but the type checker isn't quite smart enough. This issue came up in a larger real world example, but this was the minimal reproduction I could think of.
The text was updated successfully, but these errors were encountered: