Skip to content

Concrete object not assignable to a generic mapped type with partially concrete constraint #49063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Andarist opened this issue May 11, 2022 · 3 comments · May be fixed by #49064
Open

Concrete object not assignable to a generic mapped type with partially concrete constraint #49063

Andarist opened this issue May 11, 2022 · 3 comments · May be fixed by #49064
Labels
Needs Investigation This issue needs a team member to investigate its status.
Milestone

Comments

@Andarist
Copy link
Contributor

Bug Report

🔎 Search Terms

concrete object, assignable, generic mapped type, concrete constraint, partially

🕗 Version & Regression Information

  • This is the behavior in every version I tried (interestingly though the intersected variant of this target type, presented in the playground, became valid in TS 3.6)

⏯ Playground Link

Playground link with relevant code

💻 Code

type ExtractEvent<
  TEvent extends { type: string },
  TEventType extends TEvent["type"]
> = TEvent extends {
  type: TEventType;
}
  ? TEvent
  : never;

type TransitionConfig<TContext, TEvent extends { type: string }> = {
  actions?: {
    type: string;
  };
};

type IntersectedTransitionConfigMap<TContext, TEvent extends { type: string }> = {
  [K in TEvent["type"]]?: TransitionConfig<TContext, ExtractEvent<TEvent, K>>;
} & {
  "*": TransitionConfig<TContext, TEvent>;
};

type TransitionConfigMap<TContext, TEvent extends { type: string }> = {
  [K in TEvent["type"] | "*"]?: K extends "*"
    ? TransitionConfig<TContext, TEvent>
    : TransitionConfig<TContext, ExtractEvent<TEvent, K>>;
};

export function genericFn<TEvent extends { type: string }>() {
  const wildcardTransitionConfig = {
    "*": { actions: { type: "someAction" } },
  } as const;

  // this should be assignable, in the same way as the following assignment is OK
  let test: TransitionConfigMap<
    { counter: number },
    { type: TEvent["type"] }
  > = {} as typeof wildcardTransitionConfig;

  // concrete prop is assignable to the concrete prop of this mapped type
  test["*"] = {} as typeof wildcardTransitionConfig["*"];

  // similar intersected type accepts this concrete object
  let test2: IntersectedTransitionConfigMap<
    { counter: number },
    { type: TEvent["type"] }
  > = {} as typeof wildcardTransitionConfig;
}

🙁 Actual behavior

The concrete object is not assignable to this generic mapped with a partially concrete constraint

🙂 Expected behavior

This should be allowed, or the second assignment (the one to test['*']) should also be considered as invalid.


The problem originates here where this relation check fails:

indexedAccessType // { readonly "*": { readonly actions: { readonly type: "someAction"; }; }; }[(("*" | TEvent["type"]) & "*") & K]
templateType // (K extends "*" ? TransitionConfig<{ counter: number; }, { type: TEvent["type"]; }> : TransitionConfig<{ counter: number; }, ExtractEvent<{ type: TEvent["type"]; }, K>>) | undefined
isRelatedTo(indexedAccessType, templateType, RecursionFlags.Both, reportErrors) // 0

Which leads us to checking if a type is assignable to a conditional type and that is rarely even possible, as only limited scenarios are even checked for such a case (here)

@RyanCavanaugh
Copy link
Member

I'll ask since it seems likely 😅: Is there a smaller version of this repro?

@Andarist
Copy link
Contributor Author

@RyanCavanaugh how about this one? Note that I didn't really confirm with the internals of the compiler that the problem is truly the same here but it certainly looks like it.

@andrewbranch andrewbranch added the Needs Investigation This issue needs a team member to investigate its status. label May 31, 2022
@andrewbranch andrewbranch added this to the Backlog milestone May 31, 2022
@Andarist
Copy link
Contributor Author

@RyanCavanaugh would you mind taking a look at the repro linked above?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
3 participants