Platform: [example-app] why we `extends fromRoot.State` to another `state`

Created on 20 May 2018  路  11Comments  路  Source: ngrx/platform

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[x] Documentation issue or request

What is the current behavior?

There is no documentation in the whole project (maybe i did not find that either) for why "it makes sense to extends States from another states". For me as a new user of typescript and ngrx its really hard to understand whats the intention behind that behavior is. See:
https://github.com/ngrx/platform/blob/master/example-app/app/auth/reducers/index.ts#L15-L17

export interface State extends fromRoot.State {
  auth: AuthState;
}

https://github.com/ngrx/platform/blob/master/example-app/app/books/reducers/index.ts#L17-L19

export interface State extends fromRoot.State {
  books: BooksState;
}

When i remove extends fromRoot.State from both of the files i dont get any errors in IDEs (vscode,intellij). Furthermore the example project can be compiled and can be used in the browser as well. Apparently it has no advantages such as eg. for autocompletion, compiler. Im wrong?

So, my question: what is the intention of extending from other state into a state class? I hope someone can explain this!

Expected behavior:


Some explanation/description/advantages about why we extend from fromRoot.State

Example App question

Most helpful comment

@tdeschryver sure it can be closed (thanks for addressed issue). Yes i can i submit a PR (will give my best)

All 11 comments

After some research i found following statements in which cases we should extend from the root state:

1.) https://github.com/ngrx/platform/issues/852

when using selectors

2.) https://github.com/ngrx/platform/issues/503

You're only extending the root interface to get the type information when creating selectors

3.) https://github.com/ngrx/platform/issues/852

if you're using the feature state as the Store in your components

The states that are extending from the root-state are not used for created feature-selectors in the example-app. It will only used in the components. But as i said, nothing happens when removing extends fromRoot.State from State. No IDE or compile errors or autocompletion improvements.

I have also tried different constructor store type variations in the LoginPageComponent! Nothing happens: No compile error! As i said, i did not catch up the main reason point behind the usage!

  constructor(private store: Store<fromAuth.State>) {}
  constructor(private store: Store<{}>) {}
  constructor(private store: Store<any>) {}
  constructor(private store: Store<{foo: 'bar'}>) {}

The answer is exactly what you've found out.

You extend the root state so that you get type information when using selectors and if you're using the feature state as the Store in your components. If your feature module is completely independent of the root state, then you don't need to extend from the root state interface.

In the case of the example app the Auth module might not be using any of the information from the root module (layout, router). But it is good to extend from the root state in case of future uses, it does no harm to extend the interface since these information are not included when TypeScript is compiled anyway.

@joscmw95 thank you for your response.

I know this leads to support question but i want to know what are may could be future uses?

For example is in the root core state's store there is data regarding the user. Then feature modules/states that needs it will inject FeatureState which extends CoreState and have type information regarding both states' data.

Personally, I put my authentication state in the root and use it in every feature module to check whether the user is authenticated.

...and have type information regarding both states' data.

thank you i got it! , its "only" useful when we need the type/data information (e.g. authentication) through the coreState userState

I will reflect all the thread information in form of documentation in the example-app.

You do it the other way?

export interface RootState {
  layout: fromLayout.State;
}

export interface RootState extends AuthState {
  root: RootState;
}

Personally, I put my authentication state in the root and use it in every feature module to check whether the user is authenticated.

Sorry for my noob questions (as you above i also crossed out a few things again) !

But thank you for your help :)

I have authentication related state data in the root, i.e., user

export interface RootState {
  user: fromAuth.State;
  ...
}

Then let's say I have a Cart feature module that stores items added to the cart in an e-commerce app:

export interface CartState extends RootState {
  items: any[];
  ...
}

In cart.component.ts then I'll use Store<CartState> to select user and items:

user$ = this.store.pipe(select(state => state.user), publishReplay(), refCount());
cart$ = this.store.pipe(select(state => state.items), publishReplay(), refCount());

For further discussions you can email me at [email protected]

@joscmw95 i think we should continue the discussion right here because it has been tagged ([question], [Project: Example App]) here by @tdeschryver ! Maybe we can made code and documentation examples for the example-app!

Hi, I was wrapping my head around the question before answering.
But @brandonroberts and @joscmw95 have already provided a good answer.

I think this will be addressed in #861 but if you want you can submit a PR.

Is it OK if I close the issue?

@tdeschryver sure it can be closed (thanks for addressed issue). Yes i can i submit a PR (will give my best)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sandangel picture sandangel  路  3Comments

alvipeo picture alvipeo  路  3Comments

hccampos picture hccampos  路  3Comments

brandonroberts picture brandonroberts  路  3Comments

mappedinn picture mappedinn  路  3Comments