-1

What follows is an example of issue with an expected outcome:

const actionTypes = {
  name: {
    set: "name/set",
  },
} as const;

type ActionTypes = { [key: string]: (string | ActionTypes) }; //record value is string or ActionTypes

// "GetActionType" circularly references itself
type GetActionType<A extends ActionTypes> = A extends Record<
  string,
  infer Value
>
  ? Value extends string
    ? Value
    : GetActionType<Value> // "GetActionType" is not generic
  : unknown;

type SiteAction = GetActionType<typeof actionTypes>; // "GetActionType" is not generic
// expected to be 'name/set'

Is there a way to accomplish this without running into an error?

Edit

Adds as const to declaration of actionTypes nad references the constant correctly below

TypeScript version 4.0.2

Playground link.

Mateja Petrovic
  • 3,799
  • 4
  • 25
  • 40

1 Answers1

1

Following should work:

Two main diff from your approach:

  • flipped Value extends string to Value extends ActionTypes for recursion
  • marked siteActionTypes to as const to infer specific types
const siteActionTypes = {
  name: {
    set: 'name/set'
  }
} as const

type ActionTypes = { [key: string]: string | ActionTypes }

type GetActionType<A extends ActionTypes> = A extends Record<string, infer Value>
  ? Value extends ActionTypes
    ? GetActionType<Value>
    : Value
  : unknown

type SiteAction = GetActionType<typeof siteActionTypes>
// SiteAction has type 'name/set'

Typescript Playground

Pritam Kadam
  • 2,388
  • 8
  • 16
  • Still have the same errors can you post a repl link? – Mateja Petrovic Sep 14 '20 at 14:25
  • Added in the answer, this could be the version issue. This works on typescript nightly build. They seem to have fixed something in nightly – Pritam Kadam Sep 14 '20 at 14:28
  • The link points to an incomplete example, but you're right! – Mateja Petrovic Sep 14 '20 at 14:32
  • Thanks, I've complicated the [example](https://www.typescriptlang.org/play?ts=4.1.0-dev.20200914#code/MYewdgzgLgBAhsKBLcAVAngBwKYRgXhgG8AoGGMOAW2wC5izyYJsp6AiSmgehanYA0jAL5DyceqSYwARvQDkceWKbBJjaQBMF2ZRpjCRJYfDyhIUANwkSULNhgBBRCjAYceQkRgBtANbY6PTQAE5IYADmALr0ABSh4REwAD5OLmj2EACUBtYk3Nww7ADirM7IGTjsMMBIIcAArgA2cCFN6DAh2ABm2F1gwLgwSFAsTd229jClUOWu7tgAPI4w2AAeUNhgmnhzlbgAfAROqxtbOzAAStigIZqLjAmRKuG9ITAAanBNDdgkB4wAPyfb6-U6bba7dJuTL6YEzPYwnCLL4-bAA6T0VG-Rj0BpgPxgEAAdzAeTsOBgAGURthEccEdCFosKdgQN14EzMgdrAUKNRsLxWCkYIp5CL5LoSEA) slightly to see if the solution holds and it does. – Mateja Petrovic Sep 14 '20 at 14:36