Open
Description
TypeScript Version: 3.7.x, 3.8.1, 3.9.x (next)
Search Terms: Generic constraint 2344
Code
type KeyOf<T> = keyof ((T extends any ? (k: T)=>void : never) extends ((k: infer I)=>void) ? I : never);
type Constraint<T> = KeyOf<T> extends never
? any
// : KeyOf<any> extends KeyOf<T>
// ? any
: (
'a' extends KeyOf<T>
? never
: any
);
type ForceConstraint<T> = T extends Constraint<T> ? T : never;
interface Interface<T extends Constraint<T>> {
b: string;
}
type Infer<CB> = CB extends () => infer TReturn
? ForceConstraint<TReturn>
: never;
type InferWithConstraint<CB> = ForceConstraint<Infer<CB>>;
type InferInterfaceFromCallback<CB> = Interface<InferWithConstraint<CB>>; // invalid => NOT OK
type InferInterfaceFromCallback1<CB> = Interface<Infer<CB>;> // invalid too => NOT OK
// just debug purpose
type A1 = Interface<unknown>;
type A2 = Interface<any>; // invalid => OK
type A3 = Interface<never>;
type A4 = Interface<undefined>;
type A5 = Interface<number>;
type A6 = Interface<string>;
type A7 = Interface<null>;
type A8 = Interface<object>;
type A9 = Interface<{}>;
type A_FAIL1 = Interface<{ a: 'b' }>; // invalid => OK
type A_FAIL2 = Interface<{ a: 'b' } | 1>; // invalid => OK
Expected behavior:
type InferInterfaceFromCallback<CB> = Interface<InferWithConstraint<CB>>;
Should be valid
Explanation:
So, i was trying to apply a specific constraint on a generic type.
Constraint<T>
'returns' never if T contains a property called a
, else it returns any
ForceConstraint<T>
tries to help typescript to know if T is valid, else it returns never
Interface<T extends Constraint<T>>
forces its generic type to respect Constraint
Infer<CB>
infers the return type of CB and ensures it follows Constraint
InferWithConstraint<CB>
forces again Infer<CB>
to be compliant with Constraint
(even if it is already)
So Interface<InferWithConstraint<CB>>
should be valid, sadly, typescript reports:
TS2344: Type 'ForceConstraint<Infer<CB>>' does not satisfy the constraint 'Constraint<ForceConstraint<Infer<CB>>>'.
Potentially related issues: