Skip to content

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

Closed
@Andarist

Description

@Andarist

πŸ”Ž 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 @weswigham (since it's a change from #56742 )

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