-
Notifications
You must be signed in to change notification settings - Fork 142
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
Add TypeScript definitions to enforce or infer whether properties are required. #114
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a few minor notes, but overall I think this is great and what I was wanting but had absolutely no idea how to do in TS. I like that this feels intuitive to use and would provide a lot of good information to devs.
I need to do more focused reading, but my blunt question is which of the two alternatives is best? From skimming them on my phone, I was drawn to this one to review it a bit more fully but unfortunately I just haven't had a lot of spare time to make a fair judgement.
src/index.d.ts
Outdated
export interface FluxStandardAction< | ||
Payload = undefined, | ||
Meta = undefined, | ||
Type extends string = string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious what the benefit of creating Type
and using the extends
keyword is, as opposed to just saying it must be a string
. I'm not up to speed on the latest TS trends 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In TypeScript you can restrict a type to a constant value.
For a Counter application example this makes it possible to change the following code:
import { FSA } from 'flux-standard-action';
const INCREMENT_COUNTER = 'INCREMENT_COUNTER';
type INCREMENT_COUNTER = typeof INCREMENT_COUNTER;
interface IncrementCounterAction extends FSA {
type: INCREMENT_COUNTER;
}
to this:
import { FSA } from 'flux-standard-action';
const INCREMENT_COUNTER = 'INCREMENT_COUNTER';
type IncrementCounterAction = FSA<undefined, undefined, typeof INCREMENT_COUNTER>;
removing the need to re-declare the type
property. An object using a string, but different to 'INCREMENT_COUNTER' would thus not implement the IncrementCounterAction
type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@couven92 Why would we want to put the Type
generic to be last? This would mean we would always have to explicitly type meta whether the action has meta or not.
I think I would prefer to put tType
first as it is the primary property of an FSA and I want to always strongly type my action types for discriminitive unions in redux reducers. Where as quite a lot of my action don't utilise the Meta
property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My opinionated take on this is on the master branch of this fork if you want to have a look https://github.com/hally9k/flux-standard-action
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see #114 (comment)
Okay, first off, from what I can tell both my suggestion and #112 would work. I am going to argue for my suggestion (i.e. #114).
Disadvantages:
|
And if we go for my option, can we please agree on a name for the automatically inferred requiements type? I do not really like |
Any movement on this? |
@Neaox I'll do the rebase now, and make verything good again, but well... This has been ready for merge since 10th November 2018. Unless someone objects to my naming, but that did not seem to be the case |
Co-Authored-By: couven92 <fredrik.rasch@gmail.com>
Fix and refactor TypeScript tests
Hey, the master branch is basically unusable in the context of my redux application, this appears to address all the issues I have though. If we can't strong type |
After reading into this a bit further I am of the opinion that we should switch the order of the generics around to |
@hally9k yes, switching the arguments around would also be my preference. However, that would be a breaking change that I did not want to introdruce with this PR. I suggest a new issue or PR with these changes, since that really is not part of the changes proposed here. |
Hi folks, sorry for the delay on this. I think I would prefer merging the most performant version and just releasing that. No need to worry about breaking changes for now. |
@JaKXz ok, that's great. Pushed new changes and updated the PR description on top :) |
@JaKXz because of breaking changes this PR should probably be merged with a new version number? Do you want me to increase the version here in the PR? Major increase? (i.e. |
Don't worry about the package version, I will follow the release process, later tonight hopefully! |
There are some updates I would like to make to the tests and what not but I didn't want them to block the release any more. |
@couven92 Nice!! 🚀 🚀 🚀 |
@hally9k & @couven92 - I'm curious, why did you guys want to change the ordering to |
@thisissami Hey, one of the most important requirements to be able to add type safety to redux reducers is having the
For this reason, in my code I always type the |
Oh interesting. So in that case, when you create a reducer, you set the action paramater's type as a union of the possible very specific |
Alternative to PR #112 (documented in #109). Introduces breaking changes
Introduce
FSAWithPayload
andErrorFSAWithPayload
Introduce
FSAWithMeta
andErrorFSAWithMeta
Introduce
FSAWithPayloadAndMeta
andErrorFSAWithPayloadAndMeta
Introduce
FSAAuto
andErrorFSAAuto
which infers which FSA type to use based on the type argument beingundefined
or not.So
FSAAuto
(i.e.FSAAuto<undefined, undefined>
) maps toFSA
, whileFSAAuto<any>
maps toFSAWithPayload
sinceany
does not extendundefined
.I'd be very happy for alternative naming suggestions. Maybe
FSAInfer
orFSAAutoRequire
is better?UPDATE: Because of more sensible usability, the
Type
generic argument for FSA-types has been moved to the first position (i.e.FSA<Payload, Meta, Type>
→FSAAuto<Type, Payload, Meta>
. All type arguments are optional, withType
defaulting tostring
,CustomError
defaulting toError
, andPayload
andMeta
defaulting toundefined
allowing forFSA
to automatically becomeFSA<string, undefined, undefined>
.Introducing the generic type argument
Type
is inspired from PR #113, however the decision was made to introduce a breaking change by changing the order of the generic type arguments.