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

Issue with void Param after Typescript 3.4 #14

Open
jasonvasquez opened this issue Apr 30, 2019 · 6 comments
Open

Issue with void Param after Typescript 3.4 #14

jasonvasquez opened this issue Apr 30, 2019 · 6 comments
Assignees

Comments

@jasonvasquez
Copy link

jasonvasquez commented Apr 30, 2019

Hello,

I've been using typescript-fsa-redux-thunk combined with typescript-fsa-reducers for quite some time now very happily - thankyou!

Today, I upgraded several of my projects to Typescript 3.4, at which point many of my thunk-based actions suddenly were not working properly in my reducers. Specifically, I have simple async actions defined somewhat like:

const doThing = createAsyncAction<void, number>("DO_THING",
  async () => {
    return 1;
  },
);

with reducers structured like:

...
.case(doThing.async.done, (state, {result}) => ({
  ...state,
  newValue: result,
}))
...

This worked fine in the past, I was able to use them simply in calls like dispatch(doThing.action()), reducers worked as expected.

Today, I can define the actions fine, but in the reducers, I receive this typescript compilation error:

Type '(action: AnyAction) => action is Action<Failure<void, Error>>' is not assignable to type '(action: AnyAction) => action is Action<{ params: void; } & { error: Error; }>'.
  Type predicate 'action is Action<Failure<void, Error>>' is not assignable to 'action is Action<{ params: void; } & { error: Error; }>'.
    Type 'Action<Failure<void, Error>>' is not assignable to type 'Action<{ params: void; } & { error: Error; }>'.
      Type 'Failure<void, Error>' is not assignable to type '{ params: void; } & { error: Error; }'.
        Type '{ params?: void | undefined; } & { error: Error; }' is not assignable to type '{ params: void; } & { error: Error; }'.
          Type '{ params?: void | undefined; } & { error: Error; }' is not assignable to type '{ params: void; }'.
            Property 'params' is optional in type '{ params?: void | undefined; } & { error: Error; }' but required in type '{ params: void; }'.

It looks like it is due to this rule in typescript-fsa:

export type Success<Params, Result> =
  ({params: Params} | (Params extends void ? {params?: Params} : never)) &
  ({result: Result} | (Result extends void ? {result?: Result} : never));

Basically, Params extends void fires here, meaning params should be defined as params?, but I think they're being passed in as params: void.

I hope I interpreted that issue correctly. If I have a type other than void for the thunk param, then everything compiles fine. This code worked prior to Typescript 3.4, so I'm presuming a more thorough type checking has occurred here to catch this particular one.

Relevant packages:

"typescript": "^3.4.5",
"typescript-fsa": "^3.0.0-beta-2",
"typescript-fsa-reducers": "^1.2.1",
"typescript-fsa-redux-thunk": "^2.0.0-beta.11",

Let me know if I can provide any other details!

@xdave
Copy link
Owner

xdave commented May 3, 2019

@jasonvasquez this is a known problem with how the typings of typescript-fsa work with a feature for this project that allows optional parameters. I've offered some insight upstream, but there's been little to no activity (aikoven/typescript-fsa#56).

For this, there's a couple of different solutions for what to change on the doThing thunk:

  1. Leave out the type parameters on createAsyncAction (everything is inferred):
const doThing = createAsyncAction("DO_THING",
  async () => {
    return 1;
  },
);
  1. Or, use {} instead of void:
const doThing = createAsyncAction<{}, number>("DO_THING",
  async () => {
    return 1;
  },
);

Let me know if this works for you

@xdave xdave self-assigned this May 3, 2019
@jasonvasquez
Copy link
Author

Alright, cool - thanks!

@septs
Copy link
Contributor

septs commented Sep 16, 2019

@xdave in TypeScript 3.6 use unknown replace void?

createAsync<unknown, number>("example")

@xdave
Copy link
Owner

xdave commented Sep 16, 2019

I just implemented a fix for the return type, I could probably do the same for the params...

@septs
Copy link
Contributor

septs commented Aug 16, 2020

Maybe this is the right way

const doThing = createAsyncAction("DO_THING",
  async (): Promise<number> => {
    return 1;
  },
);

@xdave
Copy link
Owner

xdave commented Aug 17, 2020

Perhaps. New eslint seems to like to enforce doing that.

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

No branches or pull requests

3 participants