Skip to content

Generic constraint generates a TS2344  #36852

Open
@lifaon74

Description

@lifaon74

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

Playground Link

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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs InvestigationThis issue needs a team member to investigate its status.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions