Why is U
being inferred as unknown
in foo
?
Could it not look at UnwrappedArray
and known that U
must be a string
or yet another UnwrappedArray
?
Is there any hints that I can give to the compiler to help it out?
type Unwrap<T> = T extends string ? T : T extends Array<infer U> ? UnwrappedArray<U> : never;
interface UnwrappedArray<T> extends Array<Unwrap<T>> {}
let a: string = "hello";
let b: Unwrap<string> = a;
a = b;
let c: Array<string> = [a];
let d: Unwrap<Array<string>> = c;
c = d;
function foo<A>(unwrapped: Unwrap<A>): A {
// This fails.
return unwrapped;
}
Type 'Unwrap<A>' is not assignable to type 'A'.
'A' could be instantiated with an arbitrary type which could be unrelated to 'Unwrap<A>'.
Type 'A | (A extends (infer U)[] ? UnwrappedArray<U> : never)' is not assignable to type 'A'.
'A' could be instantiated with an arbitrary type which could be unrelated to 'A | (A extends (infer U)[] ? UnwrappedArray<U> : never)'.
Type 'A extends (infer U)[] ? UnwrappedArray<U> : never' is not assignable to type 'A'.
'A' could be instantiated with an arbitrary type which could be unrelated to 'A extends (infer U)[] ? UnwrappedArray<U> : never'.
Type 'UnwrappedArray<unknown>' is not assignable to type 'A'.
'A' could be instantiated with an arbitrary type which could be unrelated to 'UnwrappedArray<unknown>'.(2322)
I give a counter example, let's just think when A
is ['1']
type, so when we use type Unwrap<A>
to transform it, due to interface UnwrappedArray<T> extends Array<Unwrap<T>> {}
, finally, UnwrappedArray<U>
would be equal to Array<'1'>
which is not initial type ['1']
. This is demonstrated by:
let e: Array<"hello"> = ["hello"];
let f: Unwrap<Array<string>> = e;
// Counter example.
e = f;
To solve this problem, you can try the following change:
type Unwrap<T> = T extends string
? T
: T extends Array<infer U>
// U extends Unwrap<U>, the following line can be simplified like that, thx for the suggestion
? U extends Unwrap<U>
? T
: never
: never;
let a: string = "hello";
let b: Unwrap<string> = a;
a = b;
let c: Array<string> = [a];
let d: Unwrap<Array<string>> = c;
c = d;
function foo<A>(unwrapped: Unwrap<A>): A {
return unwrapped;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.