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

fix: reducers and effects with same name are correctly typed 4.3.X #913

Merged
merged 2 commits into from
Jul 7, 2021

Conversation

semoal
Copy link
Member

@semoal semoal commented Jul 6, 2021

Resolves #912

Before 4.3 TypeScript accepted "duplicated" types but now is more stricter, so we just merge them giving priority always to reducers because is the entrypoint (will be the first executed if the same is duplicated)

@github-actions
Copy link

github-actions bot commented Jul 6, 2021

size-limit report 📦

Path Size
./packages/core/dist/core.umd.production.min.js 1.42 KB (0%)
./packages/immer/dist/immer.umd.production.min.js 143 B (0%)
./packages/loading/dist/loading.umd.production.min.js 597 B (0%)
./packages/persist/dist/persist.umd.production.min.js 172 B (0%)
./packages/select/dist/select.umd.production.min.js 456 B (0%)
./packages/updated/dist/updated.umd.production.min.js 407 B (0%)

Copy link
Collaborator

@tianzhich tianzhich left a comment

Choose a reason for hiding this comment

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

Nice utility type. Good job mate. Do we need to add a notice about this case: if the same name used in both reducer and effects, the reducer will be executed first, and then the effects:

function createEffectsMiddleware<
	TModels extends Models<TModels>,
	TExtraModels extends Models<TModels>
>(bag: RematchBag<TModels, TExtraModels>): Middleware {
	return (store) => (next) => (action: Action): any => {
		if (action.type in bag.effects) {
			// first run reducer action if exists
			next(action)

			// then run the effect and return its result
			return (bag.effects as any)[action.type](
				action.payload,
				store.getState(),
				action.meta
			)
		}

		return next(action)
	}
}

I can't figure out this executing order until I read the above source code.

@tianzhich
Copy link
Collaborator

Or we should remind our users not to use this way which I think is confusing. In my opinion, we can use a more semantic name on effects if it conflicts with the reducer.

@semoal
Copy link
Member Author

semoal commented Jul 7, 2021

Or we should remind our users not to use this way which I think is confusing. In my opinion, we can use a more semantic name on effects if it conflicts with the reducer.

Technically, our recommendation is to use Uppercase for reducers and effects with camelcase in that way you can differentiate easily on Redux Devtools. But... as we accept reducers and effects with the same name, we have to accept that on typings too

@semoal
Copy link
Member Author

semoal commented Jul 7, 2021

Nice utility type. Good job mate. Do we need to add a notice about this case: if the same name used in both reducer and effects, the reducer will be executed first, and then the effects:

function createEffectsMiddleware<
	TModels extends Models<TModels>,
	TExtraModels extends Models<TModels>
>(bag: RematchBag<TModels, TExtraModels>): Middleware {
	return (store) => (next) => (action: Action): any => {
		if (action.type in bag.effects) {
			// first run reducer action if exists
			next(action)

			// then run the effect and return its result
			return (bag.effects as any)[action.type](
				action.payload,
				store.getState(),
				action.meta
			)
		}

		return next(action)
	}
}

I can't figure out this executing order until I read the above source code.

oh, i thought it was the inverse... let me check

@semoal
Copy link
Member Author

semoal commented Jul 7, 2021

@tianzhich Just introduced a new test to check the order of execution and don't introduce any regression there, also i replaced the order of the merge exclusive to give priority to reducers type.

Where the scenario of:

state: {
  count: 0,
},
reducers: {
  add(state, payload: string) {
    return state
  },
},
effects: () => ({
  add(payload: number) {
  },
}),

store.dispatch.add() will type the payload as string

@tianzhich
Copy link
Collaborator

well, now it's no problem for me.

@semoal semoal changed the title fix: Merges ModelDispatcher types instead of & fix: reducers and effects with same name are correctly typed 4.3.X Jul 7, 2021
@semoal semoal merged commit 3db2d9f into main Jul 7, 2021
@semoal semoal deleted the fix-912 branch July 7, 2021 08:24
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.

Upgraded 4.1.2 to 4.3.X of TypeScript and never is returned when calling effect-reducer with same name
2 participants