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 ts-toolbelt for 'compose' types #3563

Closed
wants to merge 1 commit into from
Closed

Conversation

jednano
Copy link
Contributor

@jednano jednano commented Sep 4, 2019

In response to #3536 (comment)

ts-toolbelt

@@ -69,7 +69,7 @@ export default function applyMiddleware(
dispatch: (action, ...args) => dispatch(action, ...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose<typeof dispatch>(...chain)(store.dispatch)
dispatch = compose(...chain)(store.dispatch as typeof dispatch)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The next step is to get the chain properly typed so we don't need to do this casting.

export default function compose<R>(...funcs: Function[]): (...args: any[]) => R

export default function compose(...funcs: Function[]) {
const compose = <Fns extends F.Function<any[], any>[]>(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I really wanted to use ts-toolbelt's F.compose here, but it was swallowing types. This way, I can be more explicit and get an accurate return type.

if (funcs.length === 0) {
// infer the argument type so it is usable in inference down the line
return <T>(arg: T) => arg
// TODO: should probably throw an error here instead
return (<T>(arg: T) => arg) as any
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TypeScript really doesn't like this line, because it goes against the return type. Rather than introducing a union type, I just cast it as any, but I think it might make more sense to just throw an error instead. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

I was able to make this type check in my implementation of compose. However, as I suggested in comments on that PR, I think you're right that this is strange anyhow. However, I think it should simply be statically not allowed by not providing overloads for compose that take 0 arguments rather than allowing it and throwing a runtime error.

I would go farther and say that passing compose a single function is also strange behavior and probably shouldn't be allowed, but I can see why you all might want to keep that due to the current behavior, whereas I doubt anyone has much use for or would miss it accepting 0 args.

@cellog
Copy link
Contributor

cellog commented Sep 5, 2019

brilliant!

package.json Show resolved Hide resolved
@timdorr timdorr changed the base branch from ts-conversion to master September 6, 2019 20:30
@jednano
Copy link
Contributor Author

jednano commented Sep 6, 2019

Just rebased against master.

@timdorr
Copy link
Member

timdorr commented Sep 6, 2019

Looks like I broke master. I'll get that fixed up soon.

@markerikson
Copy link
Contributor

I'd prefer to avoid adding a dependency just for one lousy function if possible. Can the compose function/type be copy-pasted or something?

@jednano
Copy link
Contributor Author

jednano commented Sep 6, 2019

The compose type is way more complex than a simple copy paste. It has dependencies that have dependencies. I also foresee this toolbelt coming in handy in future PRs for improving types.

I did have a copy paste branch before and it was significant enough that I welcomed the dependency approach more.

What is your main concern about the dependency? If it has anything to do with footprint, it has no footprint.

@markerikson
Copy link
Contributor

I generally want to minimize increasing the number of dependencies that users have to download. Sure, it's "just one more dependency", but that's how we ended up with 1500 deps being pulled down for a basic CRA+TS app. As it is, it annoys me that we have forced dependencies on loose-envify and symbol-observable. I'm okay with dev dependencies, but ideally, Redux would have zero app-level dependencies.

@timdorr
Copy link
Member

timdorr commented Sep 7, 2019

The good news is it ships zero actual JS and should get fully shook out by any bundler: https://bundlephobia.com/[email protected]

Unfortunately, compose is exactly the kind of function that TS wasn't built for. You basically have to build a recursive state machine inside of the types. It's really complex stuff, even to trace through with the source available.

@jednano
Copy link
Contributor Author

jednano commented Sep 7, 2019

Do we have any issues with the Apache 2 license here? Concerning copy/paste.

@timdorr
Copy link
Member

timdorr commented Sep 7, 2019

I don't think we need to copypasta into this repo. We can incur the dep because it has no impact on bundle sizes.

@markerikson
Copy link
Contributor

Agreed on the bundle size thing, but this is still going to require end consumers to pull down one more extra package, right?

@timdorr
Copy link
Member

timdorr commented Sep 7, 2019

Yes, and just one. ts-toolbelt has no deps of its own.

@markerikson
Copy link
Contributor

Semi-related tangent: what is loose-envify even used for, and are we still using it? For that matter, if we're doing a major, is there any way we can drop symbol-observable?

@jednano
Copy link
Contributor Author

jednano commented Sep 7, 2019

Rebased

@netlify
Copy link

netlify bot commented Sep 7, 2019

Deploy preview for redux-docs ready!

Built with commit bd9b100

https://deploy-preview-3563--redux-docs.netlify.com

@markerikson
Copy link
Contributor

Just filed #3567 to discuss trying to drop all external dependencies.

@joshburgess
Copy link
Contributor

joshburgess commented Sep 8, 2019

I opened a new PR attempting to rewrite compose from scratch: #3568

@jednano
Copy link
Contributor Author

jednano commented Sep 8, 2019

I can do a separate copy/pasta PR when I have some more time on Monday. Have a good weekend y'all!

@jednano
Copy link
Contributor Author

jednano commented Sep 10, 2019

Closing because we can't come to a consensus about the 3rd-party dependency.

@jednano jednano closed this Sep 10, 2019
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.

5 participants