I have stumbled upon issue with TypeScript types where I can't assign narrower type to more broad one when generics with conditions are present. However, all the generic paramters are fully instantied so TypeScript should be able to resolve both types fully and compare them based on types of each property.
This is simplified version of what I was trying to do which throws the error:
// Returns keyes that have type extending Types
type KeysMatching<T, Types> = { [K in keyof T]: T[K] extends Types ? K : never }[keyof T];
type Mapping = {
STR: string;
NUM: number;
BOOL: boolean;
}
type Values = Mapping[keyof Mapping];
type Generic<T extends Values> = {
typeStr: KeysMatching<Mapping, T>
}
const foo: Generic<boolean> = { typeStr: 'BOOL' };
const bar: Generic<Values> = foo;
// Type 'Generic<boolean>' is not assignable to type 'Generic<Values>'.
// Type 'Values' is not assignable to type 'boolean'.
// Type 'string' is not assignable to type 'boolean'.(2322)
The sample is also available in TypeScript playground
I have found this answer on SO which states
If a conditional type contains an unresolved type parameter (such as T) typescript will not try to reason much about the conditional type.
however, all of the conditional types should be resolved here.
I don't get why TypeScript first says 'Generic<boolean>' is not assignable to type 'Generic<Values>' and then it switches it around that 'Values' is not assignable to type 'boolean', but I am trying to assign boolean to Values.
Can anybody explain why TypeScript throws this error?
Edit:
If I remove the condition from KeysMatching type, the assignment does not throw error so it seems like it's connected with the condition, but all the generic types should be resolved when checking assignability of the type.
I tried it with more simple case including conditions and it doesn't throw error:
type Conditional<T, V> = T extends V ? T : unknown;
const foo2: Conditional<string, Values> = 'string';
const bar2: Conditional<Values, Values> = foo2;