-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Help me understand 'Types.RootState' #85
Comments
This is a global scope type annotation, if you'd open project and search all references everything should be clear |
Thanks for this guide. There is still the challenge of how and where to create the "RootState" type. There should be a State type defined in each of the separate reducers. I guess file containing the combine reducers is the appropriate place for the RootState type. Makes sense? |
@carpben I'm using Ambient Modules technique, you can learn more here: And also here: #97 |
I use For example :
Then it
|
@chawax I used that in the past but it's not an optimal solution and introduces all kind of issues when scaling your codebase, primarily because then in your components you are adding hard-dependency on this module like this: import {RootState} from '../../rootReducer'; <= hard dependency It will add all of your reducers and their dependencies as a dependency to your components and you'll have to mock tons of unrelated stuff when trying to test in isolation. That means you have tight coupling in your codebase and this is considered a code smell. With my approach (the one that is using purely ambient type definition to define global scope types using |
@chawax I just realized there is more to my argument above that needs to be added here:
type RootState = import("../../rootReducer'").RootState;
// but it's still more cumbersome to use and more error-prone
// when using with other global types, consider comparing it to this:
import { RootState, Services, RootAction, TodoModel, ... } from '@Types';
|
Something like that ?
with Then :
|
Yes correct, but notice I prefer to add "Ambient Modules" technique (linked above) because that gives me absolute import capability, without paths mapping and aliasing configuration concerns. I don't really like relative imports for global stuff because it's hard to maintain. |
I don'k now ambient modules (a lot of things to learn about TS yet !). Do you have any example how you declare such modules to have absolute imports ? |
Please check |
Great ! Thanks a lot ! |
When RootState is imported would you consider it to be a hard import?
|
Ad1) By hard dependency I mean that you have a runtime dependency that you have to mock it during testing in isolation. I agree the example I have provided is not the best one, but you can imagine real-world situation (commonly happens with the ducks-pattern), when you're importing the type (State, ActionType) and some other runtime export (selectors, actionCreators) from the same file, then it'll be a problem. Ad2) I don't understand your question. An ambient definition doesn't import anything, you simply extend its definition across multiple files, that's how it works. |
import {RootState} from '../../rootReducer'; <= hard dependency Though it just imports a type, it will make rootReducer a dependency of the component file, which will create a problem when trying to test the component independently? |
No no, when only importing type it is removed on the compilation step so it's fine, but you're opening a gate to import some other runtime exports (like selectors, actionCreators, type constants etc.) from the same file, then it's starting to be complicated and problematic |
Thanks @piotrwitek. I think this technique makes sense. |
Sorry if this was a dump question- In this connected component, I'm confused about the
Types
andTypes.RootState
. Is theTypes
a npm package cuz it doesn't seem to be in thepackage.json
?The text was updated successfully, but these errors were encountered: