Search code examples
angularstorestrong-typing

What is the purpose of strongly typing the store in NgRx?


CoreModule is an eagerly loaded module containing the state needed at application start.

import * as fromCore from './state/core.reducer';

@NgModule({
  ...
  imports: [
    StoreModule.forRoot({ core: fromCore.reducer }),

DocumentModule is a lazy loaded module.

import * as fromDocument from './state/document.reducer';

@NgModule({
  ...
  imports: [
    StoreModule.forFeature('document', fromDocument.reducer),

DocumentComponent injects the store.

import * as fromDocument from './state/document.reducer';

constructor(private store: Store<fromDocument.State>) { }

fromDocument.State extends the 'core' state.

import * as fromCore from '../../core/state/core.reducer';

export interface State extends fromCore.State {
    document: DocumentState;
}

This is an approach I see used everywhere, but I don't see any benefit to it. When I set it up so that fromDocument.State does not extend fromCore.State, I can still access the 'core' part of the state tree in DocumentComponent.

this.user$ = this.store.select(fromCore.getUser);

By injecting the store in a component I always have access to the complete state tree, regardless how I type the store. So what exactly is the purpose of strongly typing the store? Why not just use Store<any> everywhere? The only way I interact with the store object is store.select and store.dispatch so there is no typing benefit as far as I can see?


Solution

  • Specific point

    In the specific case you mentioned, the typing will help with the overload of select that takes a mapping function as argument, e.g. this.store.select(s => ....).

    NgRx still let you do un-typed selection, though. Related discussion on GitHub about that : https://github.com/ngrx/store/issues/60

    Generally

    Strong typing from TypeScript and other fancy stuff (and, to be fair, most features of all programming languages) are not meant to

    • automate validation for your program
    • act as some kind of security feature (prevent data leak)

    They are meant instead as a crutch for us poor human developers to avoid doing the silly mistakes we usually write in our own code.

    Example : like trying to call user.namme instead of user.name in an obscure, forgotten part of the code, that will lead to a cascade of bugs. Imagine it shows only some "undefined" and "login error" to the user, in a strange place, and only if he does 5 very specific actions in a certain order, a bit hard to trace back and reproduce.

    This will be quickly detected by your compiler, before put in production, if you use strong typing.