microsoft / microsoft/TypeScript

Generic constraint generates a TS2344

Open
#36,852 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Needs Investigation
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

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

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:

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided Playground Link and reproduce the TS2344 diagnostic using the minimal generic-type example. Compare the expected validity of Interface<InferWithConstraint> with the reported constraint error and review related issues 31736 and 34604. Done means the valid type alias no longer produces TS2344 while the invalid examples remain rejected.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.