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

Use void instead of any for undefined payloads #174

Merged
merged 2 commits into from
Oct 13, 2019
Merged

Use void instead of any for undefined payloads #174

merged 2 commits into from
Oct 13, 2019

Conversation

Krisztiaan
Copy link

Additional layer of type security, don't let the user implicitly opt out of type checking

@netlify
Copy link

netlify bot commented Aug 14, 2019

Deploy preview for redux-starter-kit-docs ready!

Built with commit e9a9ad3

https://deploy-preview-174--redux-starter-kit-docs.netlify.com

@markerikson
Copy link
Collaborator

Hmm. A bunch of type tests fail because of this change. I'm not clear what improvement this is supposed to make.

Going to close this for now. If you still feel it's a point of concern, please let me know and we can discuss further.

@markerikson markerikson closed this Oct 7, 2019
@Krisztiaan
Copy link
Author

@markerikson thanks for taking a look, we've made this exact patch in our project using this library, and it revealed a bunch of missed or mismatched action payload typings, while forcing us to specify payload where it was expected. I would look into fixing the tests if we can agree this would be beneficial to have merged.

@markerikson
Copy link
Collaborator

markerikson commented Oct 9, 2019

Sure, sounds good.

Hmm. I don't suppose this is related to #211 at all?

@markerikson markerikson reopened this Oct 9, 2019
@markerikson
Copy link
Collaborator

@phryneas : since you're consulting, any thoughts on this one?

@markerikson
Copy link
Collaborator

So looking at the type errors, some of them from "raw" uses of PayloadAction like this:

  const action: PayloadAction = { type: '', payload: 5 }
  const numberPayload: number = action.payload

Also:

  const increment = createAction('increment')
  // Error: Argument of type '1' is not assignable to parameter of type 'void | undefined'
  const n: number = increment(1).payload

Those are fixable by adding generic to PayloadAction<number> and createAction<number>. Potentially reasonable. But, I'm not entirely sure that's "right" here.

@phryneas
Copy link
Member

Well, it would definitely change the defined behaviour.

Especially this test defines that a PayloadAction should fall back to any if there's no type defined. And #165 shows that people are using it like this.

I guess all other of those tests are building on this "acceptance criteria" that was formulated in this first test.

As for me, I'd like this to change, as those types being more strict will prevent bugs like people accidentally forgetting the type parameter and then doing werid stuff.
But this will be breaking for people.

Your call if you want this :)

@Krisztiaan
Copy link
Author

Sure, sounds good.

Hmm. I don't suppose this is related to #211 at all?

This does not seem related, as the PR would only cover the default payload type that is used when nothing is supplied

@markerikson
Copy link
Collaborator

markerikson commented Oct 11, 2019

I guess it would help if I better understood the ramifications of the type change, in terms of end-user experience, actual code usage, and tests that would have to change.

Can anyone add some clarification?

@phryneas
Copy link
Member

I think basarat describes this a whole lot better than me: https://basarat.gitbooks.io/typescript/docs/options/noImplicitAny.html

The point is: he describes noImplicitAny, which is a compiler option the user could turn on or off (they should, TS becomes pretty much useless without it). But we're a lib here, we can't leave that decision for the user and we can't detect if the user uses noImplicitAny, we have to make a decision for everyone.

The question is do we allow all our users to do something potentially dangerous by accident, or do we require them to explicitly do that dangerous thing if they really want to?

  • Either we allow people to allow createAction without type argument, which then defaults to createAction<any> and eliminates essentially all type checks along the way. (This might cause a lot of bugs for ppl who normally use it but just forget it once in a while)
  • Or we allow no-one to use createAction without a type argument (by making it useless, defaulting to something like void). They could still use createAction<any> if they really wanted, but they's have to specify that. (This might be a little inconvenient for ppl who use TS but don't care about type safety?)

As for the tests: currently, it seems to be a "business requirement" that it works as it currently does. I don't know who initially formulated it like this, and what they had in minde 🤷. I guess a few test would need to be replaced with other tests. But I also guess that would be fine.

@markerikson
Copy link
Collaborator

Yeah, I think I can get behind making the typing more explicit here, especially since most folks would be using createSlice anyway vs calling createAction themselves.

Would one of you be able to tackle this? I'd want to get it into 0.8 as well, but I want to start working on updating the tutorial contents.

@markerikson markerikson changed the base branch from master to v0.8-integration October 13, 2019 18:34
@markerikson
Copy link
Collaborator

Okay, I re-created the branch off of v0.8-integration, and fixed up the type tests so they pass. I'm not 100% sure the type test changes are correct, though. Could both of you look them over?

@@ -22,16 +22,19 @@ function expectType<T>(p: T): T {
* Test: PayloadAction type parameter is optional (defaults to `any`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defaults to any -> should not default to any

@@ -58,10 +61,12 @@ function expectType<T>(p: T): T {
payload
}),
{ type: 'action' }
) as PayloadActionCreator
) as PayloadActionCreator<number>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be number|undefined


expectType<PayloadAction<number>>(actionCreator(1))
// typings:expect-error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and these two should actually not fail then

@@ -110,22 +115,21 @@ function expectType<T>(p: T): T {
}

/*
* Test: createAction() type parameter is optional (defaults to `any`).
* Test: createAction() type parameter is required, not inferred (defaults to `void`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test doesn't really make any more sense (description does not match what it tests right now), so I would delete it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, lemme rewrite this one

@phryneas
Copy link
Member

Looks good from my side.

@markerikson
Copy link
Collaborator

great, thanks!

@markerikson markerikson merged commit cd8f9e5 into reduxjs:v0.8-integration Oct 13, 2019
markerikson added a commit that referenced this pull request Oct 15, 2019
* Create slice changes (#197)

* Include case reducers in createSlice result (#209)

* Fix missing name field in type test

* Include provided case reducers in createSlice output

- Added `caseReducers` field to the createSlice return object
- Added test and type test for returned case reducer
- Removed "Enhanced" terminology from types, and replaced with
  "CaseReducerWithPrepare" and "CaseReducerDefinition"
- Restructured logic to only loop over reducer names once, and
  check case reducer definition type once per entry

* Add type tests for correct case reducer export inference

* Rewrite caseReducers types for correct inference of state + action

* Add type test for reducers with prepare callback

* Fix type inference for actions from reducers w/ prepare callbacks

* Clean up type names and usages

* Use a generic State type in ActionForReducer

* Re-switch Slice generics order

* Use `void` instead of `any` for undefined payloads (#174)

* Change default createAction payload type to void to make it required

* Fix createAction type tests per review

* Update tutorials for v0.8 (#213)

* Update basic tutorial with createSlice changes

* Update intermediate tutorial with createSlice changes

* Update advanced tutorial with createSlice changes

* Change existing commit links to point to reduxjs org repos
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants