Open
Description
TypeScript Version: 3.2.2
Search Terms: conditional types, unions, narrowing
Code
interface A<T> {
value: T;
}
interface Specification {
[key: string]: Array<any> | Specification;
}
type Mapping<S extends Specification> = {
[key in keyof S]: S[key] extends Array<infer T> ? A<T> : Mapping<S[key]>
// Error ^^^^^^
// Type 'S[key]' does not satisfy the constraint 'Specification'.
// Type 'Specification[key]' is not assignable to type 'Specification'.
// Type 'any[] | Specification' is not assignable to type 'Specification'.
// Type 'any[]' is not assignable to type 'Specification'.
// Index signature is missing in type 'any[]'.
};
Expected behavior:
No error. "Leafs" of the Specification
tree, which have type Array<T>
(for some T
) should be mapped to A<T>
, while non-leaf properties should be recursively mapped.
Actual behavior:
In the right-hand side of the conditional type, S[key]
is not narrowed to Specification
, even if the complete type of S[key]
is Array<any> | Specification
and the Array<any>
case is catched in the left-hand side.
Playground Link: link
Related Issues: some similar issues related to conditional types, but I'm not sure whether this is a duplicate of any of them.