-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
feat(store): provide better TS errors for action creator props #3060
feat(store): provide better TS errors for action creator props #3060
Conversation
Preview docs changes for 994b640 at https://previews.ngrx.io/pr3060-994b640f/ |
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.
Neat!
modules/store/src/models.ts
Outdated
@@ -80,6 +95,8 @@ export type Creator< | |||
R extends object = object | |||
> = FunctionWithParametersType<P, R>; | |||
|
|||
type Primitive = string | number | bigint | boolean | symbol | null | undefined; |
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.
Could you also replace this usage of Primitive
please?
https://github.com/ngrx/platform/blob/master/modules/store/src/feature_creator_models.ts#L32
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 wonder if there's a reason Typescript doesn't provide this type already...
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.
Their site says
object is a type that represents the non-primitive type, i.e. anything that is not number, string, boolean, bigint, symbol, null, or undefined.
So it seems like checking if something extends
object would be sufficient.
Perhaps I shouldn't have an explicit check for primitives then.
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 need an explicit check because unknown
does not extend object
, and so it must be differentiated (but we can't check extends unknown
because every type is assignable to unknown
).
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.
It looks much better now 🎉
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.
Great work David! Thank you 🥇
There are no breaking changes when props
is used within createAction
, but props
itself has a breaking change. So, I would wait until v13 to merge this improvement.
Oh yeah, good point! |
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.
LGTM 👍
expectSnippet(` | ||
const foo = createAction('FOO', props<null>()); | ||
`).toFail( | ||
/Type 'ActionCreatorProps<null>' is not assignable to type '"action creator cannot return an array"'/ |
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.
this should be
/Type 'ActionCreatorProps<null>' is not assignable to type '"action creator cannot return an array"'/ | |
/Type 'ActionCreatorProps<null>' is not assignable to type '"action creator props cannot be a primitive value"'/ |
expectSnippet(` | ||
const foo = createAction('FOO', props<undefined>()); | ||
`).toFail( | ||
/Type 'ActionCreatorProps<undefined>' is not assignable to type '"action creator cannot return an array"'/ |
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.
this should also be
/Type 'ActionCreatorProps<undefined>' is not assignable to type '"action creator cannot return an array"'/ | |
/Type 'ActionCreatorProps<undefined>' is not assignable to type '"action creator props cannot be a primitive value"'/ |
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Closes #2892
What is the new behavior?
Does this PR introduce a breaking change?
Other information
Thanks to the advice from Nadia Chibrikova on StackOverflow,
props
can have its generic argument asserted to passNotAllowedCheck
:This provides a more precise error than the current one which is hidden within TS outputting multiple errors for a mismatch for each overload of
createAction
:Additionally, I've updated the error messages to be hopefully more explicit about what is wrong.
UPDATE: With a suggestive playground link, I took @markostanimirovic's subtle suggestion to explicitly restrict primitive types.
I've also separated the error messages to be more contextually meaningful when using
props
vs when providing a creator function tocreateAction
.