Skip to content
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

Recursive type definitions regression in 3.4.0 #30841

Closed
TerenceZ opened this issue Apr 10, 2019 · 5 comments
Closed

Recursive type definitions regression in 3.4.0 #30841

TerenceZ opened this issue Apr 10, 2019 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@TerenceZ
Copy link

TypeScript Version: 3.4.0-dev.201xxxxx

Search Terms:

Recursive
Conditional

Code

type Action<
  Args extends any[],
  Payload extends Record<string, any>,
  T extends string
> = ((...args: Args) => (Payload & { type: T })) & {
  readonly type: T
}

type AnyAction = Action<any[], any, string>

type CascadingActionMap = {
  [name: string]: AnyAction | CascadingActionMap
}

type Reducer<S, T> = (state: S, action: T) => S

type CascadingActionType<T> = T extends CascadingActionMap
  ? { [K in keyof T]: ActionType<T[K]> }[keyof T]
  : never

export type ActionType<T> = T extends AnyAction
  ? ReturnType<T>
  : T extends Reducer<any, infer A>
  ? A
  : CascadingActionType<T>

Expected behavior:
No errors. It's worth noting that it works in 3.3.4, with the correct derived type.

Actual behavior:
Running tsc command line, it reports the following errors:

error TS2456: Type alias 'CascadingActionType' circularly references itself.

914 type CascadingActionType<T> = T extends CascadingActionMap
         ~~~~~~~~~~~~~~~~~~~

error TS2315: Type 'ActionType' is not generic.

915   ? { [K in keyof T]: ActionType<T[K]> }[keyof T]
                          ~~~~~~~~~~~~~~~~

error TS2456: Type alias 'ActionType' circularly references itself.

918 export type ActionType<T> = T extends AnyAction
                ~~~~~~~~~~

error TS2315: Type 'CascadingActionType' is not generic.

924   : CascadingActionType<T>
        ~~~~~~~~~~~~~~~~~~~~~~

Playground Link:

Related Issues:

@JakeTunaley
Copy link

Recursive type aliases are, unfortunately, not supported - see #3496, #6230, and #24897 (comment).

@TerenceZ
Copy link
Author

Recursive type aliases are, unfortunately, not supported - see #3496, #6230, and #24897 (comment).

However, the code above did work before 3.4.0, and the infered type is correct.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Apr 10, 2019
@RyanCavanaugh
Copy link
Member

This didn't actually work in the past, you were just getting a silent any in most cases. Conditional types are now simplified more often and TS may detect a circularity earlier than before.

@TerenceZ
Copy link
Author

This didn't actually work in the past, you were just getting a silent any in most cases.

Nope. The following derived Types works as expected before 3.4.0 (test in 3.3.4), and no silent any.

const makeAction = <T extends string, P extends object, Args extends any[]>(
  type: T,
  fn: (...args: Args) => P,
) => {
  const action = (...args: Args) => {
    const ret = fn(...args) as P & { type: T }
    ret.type = type
    return ret
  }
  action.type = type
  return action
}

const actions = {
  a: makeAction('a', () => ({})),
  b: makeAction('b', (a: number, b: string) => ({ a, b })),
}

type Types = ActionType<typeof actions>

const fn = (data: Types) => data

fn(actions.a()) // work as expected
fn(actions.b(1, 'a')) // work as expected
fn(actions.c()) // ts error due to Property 'c' does not exist
fn({ type: 'c' }) // ts error due to Type '"c"' is not assignable to type '"a" | "b"'.ts(2322)

The Types is infered as expected (infered info from VSCode).

type Types = {
    type: "a";
} | ({
    a: number;
    b: string;
} & {
    type: "b";
})

Conditional types are now simplified more often and TS may detect a circularity earlier than before.

It means that ts >= 3.4.0 will make the above code illegal intentionally (because of detecting a circularity earlier than before)?

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants