Skip to content

[5.4 regression] Broken relation of deferred index type over a mapped type on the source sideΒ #57188

Description

πŸ”Ž Search Terms

deferred index mapped type apparent keys

πŸ•— Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play?noErrorTruncation=true&ts=5.4.0-dev.20240110#code/PTAEAEDsHsFECd7XgFXgV0gYwIYBcBLaSALlDwwFMAoPATwAdLQA1HAG3UoGcAeFAHygAvKBQBtANaU60AGZiAugG5ajZgEluAOUoA3SvH5DR4lItCUAHnkqQAJt1DjI+wxYD85KqDJyO3JSq9EygAMI43Hi8AIIANKAAQiagMZY2do5JoF5pZInB6uHQALYM6Lax6bYOTjiQdCkA3s4A0qAEkKDSsgoximQx4q0WAL6gAGSgmJIwAO6QhaEakAbw0SjVmU4ASpRYyPa8AApITOt0rTIJp9Dn9FeNzdSgbR1dPfJioJFiw4oDUCtVSjVTUTq2eD+LDMGJYPDIAAy0AA5gQsLxOqBoBUxABlSA4BjcAAW0DwCSxOLwYlgBkgNOsNSyLRClDIUXgnRRoFGQiaL289W4BEIxDIAApuITiWS8GQUASiaTyQkSjxuDgUezafS8ABKERCRUylV4EHUNShGINOEI+DItFYESpeFI1Ho3j1OgJb0CMEQwzQ2Fu+B7OT8JWy1W6uyMjK1UCs9Qcijc3n8wWBByStwMhV0uOG4RCPTQAj2VSvbV4KNmyXF411uUWq2w22h8Muu3IcNehq+hr+y1s1328MAMSQJWMLs2TO2Y-dTsxkDkhnxprllLXG5QhYZAkFuU7lAjJuV29jh8FZFcawDDKDOBhoFuegrlHsPfgSaz8CwVMuUgFEq1AdgPUA1IO3tR10TAisPCA7lW3sfZ2BweBmCwDDuCcPE8HwSgAFkXxJTpKF4QUUDCcj2HsLCugXRM9gOeAjk5bkEhtOgfy7AAfaYHDPCj7AEOJqEzV4sDohi7AVWiCHoxjW1HWAbHgF88ERUVDA4AjgJRfgtkTTiQNAQTMDQuRRJSecEyyMyUWPUAnJMrIUEFV4vHvQwvN8MRb1AXz4DBUcUGgMJiCwLDbEU5S7H4H93Kcd9P2-UNnlecQ0ixFBkt+dSKC0nTIX0tMQNicQACIK2qxQBEUJClzDM8p1KKrqogp16uHUERyKCL4rkyAktDFK3yQD80Iy+0Ujc5iPJ-GruAA+qXNYw5eCc7iYN7M8j1eMgorKCpKP814hui2LKGGxixrmyYLteP8Xrel7Ohw9A0LIAV3v+5wK2QkDAXy8bFrqBpnoBnIWsnacHuQGruvRXqLKE6zROhgG7zcULsdefqYdeawvp+pMiYB0ZxCskTXHsCawftGq6osAnYdq7BODQ6r2eBnkIbEZbavsdbiY5z7ucoXnxbIarSalsWXuHNsxGgNKZp-KjLruuxSIYCbNvY7aKpRBInPE6ifycQWjaONhOB4fhdcgfXxOg3jQzgrBLZSB2uD4P63ixT4FCZ5AnCmJzASD15Vqg4F-JRqDw-gbh-jA14gdALRdDWZ3ZMYt2JooLhnq8NzLOEmz6eesh2kF0Oc9WQwNhdt3y+btY28LvWiQEf469c030dpmuvzA-q+TBNCcMw5g5EweEiC6QI8HQBhtaF0MbYc3Z9i2-2nZo3vXf73bPdgyDLZ10-9cNg-jZ24fDJSEKJIECUg60iOJNGX7BRsm4M1WOoAZJKRGs1E+ECi5EknmBH+acQH+WGO8boMgvip24KDa2GdBRT31AA6SWEiKkXAa4BsRpQAEVIWRCiW9XgRCiAwl6Q1T78HVlNdKWtoEJTPgwBIWCBA33enbE2hkL58TPKPautl-KHVAH1VQQA

πŸ’» Code

// @noErrorTruncation: true
type Values<T> = T[keyof T];
type IsNever<T> = [T] extends [never] ? true : false;
type Cast<A, B> = A extends B ? A : B;
type Compute<A extends any> = { [K in keyof A]: A[K] } & unknown;
type Invert<T extends Record<PropertyKey, PropertyKey>> = {
  [K in keyof T as T[K]]: K;
};

interface ActorLogic<in out TSnapshot, in out TEvent extends { type: string }> {
  transition: (snapshot: TSnapshot, message: TEvent) => TSnapshot;
}

type AnyActorLogic = ActorLogic<any, any>;

interface ActorRef<TSnapshot, TEvent extends { type: string }> {
  send: (event: TEvent) => void;
  getSnapshot: () => TSnapshot;
}

type AnyActorRef = ActorRef<any, any>;

type ActorRefFrom<T> = T extends ActorLogic<infer TSnapshot, infer TEvent>
  ? ActorRef<TSnapshot, TEvent>
  : never;

interface ProvidedActor {
  src: string;
  logic: AnyActorLogic;
  id?: string;
}

declare class StateMachine<
  TChildren extends Record<string, AnyActorRef | undefined>,
> {
  children: TChildren;
}

type ExtractLiteralString<T extends string | undefined> = T extends string
  ? string extends T
    ? never
    : T
  : never;

type ToConcreteChildren<TActor extends ProvidedActor> = {
  [A in TActor as ExtractLiteralString<A["id"]>]?: ActorRefFrom<A["logic"]>;
};

type ToChildren<TActor extends ProvidedActor> = string extends TActor["src"]
  ? Record<string, AnyActorRef>
  : Compute<
      ToConcreteChildren<TActor> &
        {
          include: {
            [id: string]: TActor extends any
              ? ActorRefFrom<TActor["logic"]> | undefined
              : never;
          };
          exclude: {};
        }[undefined extends TActor["id"] 
          ? "include"
          : string extends TActor["id"]
          ? "include"
          : "exclude"]
    >;

type ToProvidedActor<
  TChildrenMap extends Record<string, string>,
  TActors extends Record<Values<TChildrenMap>, AnyActorLogic>,
> = Values<{
  [K in keyof TActors & string]: {
    src: K;
    logic: TActors[K];
    id: IsNever<TChildrenMap> extends true
      ? string | undefined
      : K extends keyof Invert<TChildrenMap>
      ? Invert<TChildrenMap>[K]
      : string | undefined;
  };
}>;

declare function setup<
  TActors extends Record<Values<TChildrenMap>, AnyActorLogic>,
  TChildrenMap extends Record<string, string> = never,
>({
  actors,
}: {
  types?: {
    children?: TChildrenMap;
  };
  actors?: {
    [K in keyof TActors]: TActors[K];
  };
}): {
  createMachine: () => StateMachine<
    Cast<
      ToChildren<ToProvidedActor<TChildrenMap, TActors>>,
      Record<string, AnyActorRef | undefined>
    >
  >;
};

πŸ™ Actual behavior

It fails to be checked

πŸ™‚ Expected behavior

The used Cast should be enough to satisfy the constraint

Additional information about the issue

We can get rid off the error (but lose functionality):

  1. if we remove id from ToProvidedActor
  2. or if we remove Compute from ToChildren
  3. or if we remove any of the intersected types within this Compute
  4. or if we remove ExtractLiteralString filter~ from ToConcreteChildren

cc Wesley Wigham (@weswigham) (since it's a change from #56742 )

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs More InfoThe issue still hasn't been fully clarified

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions