Skip to content

Contextual type can't be provided to a mapped type intersected with an object typeΒ #48812

@Andarist

Description

@Andarist

Bug Report

πŸ”Ž Search Terms

intersection, mapped type, contextual type

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ

⏯ Playground Link

Playground

πŸ’» Code

type Action<TEvent extends { type: string }> = (ev: TEvent) => void;

interface MachineConfig<TEvent extends { type: string }> {
  schema: {
    events: TEvent;
  };
  on?: {
    [K in TEvent["type"]]?: Action<TEvent extends { type: K } ? TEvent : never>;
  } & {
    "*"?: Action<TEvent>;
  };
}

declare function createMachine<TEvent extends { type: string }>(
  config: MachineConfig<TEvent>
): void;

createMachine({
  schema: {
    events: {} as { type: "FOO" } | { type: "BAR" },
  },
  on: {
    FOO: (ev) => {
      ev.type; // should be 'FOO', but `ev` is typed implicitly as `any`
    },
  },
});

πŸ™ Actual behavior

An implicit any pop-ups when the contextual type could be, somewhat easily, provided.

πŸ™‚ Expected behavior

This should just work 😜 I know a workaround for this issue - the workaround is to use a single mapped type instead of an intersection and just "dispatch" to the correct value in the template~ part of the mapped type, like here. However, this is way less ergonomic than an intersection AND the mapped type is no longer homomorphic which could matter for some cases (well, the original mapped type here is not homomorphic either, but it could be)

I already have a draft PR open to fix this issue, here. I only need some help with the stuff mentioned in the comment here

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions