A state token can be used as a representation of a state class without referring directly to the state class itself. When creating an StateToken you will provide the location that the state should be stored on your state tree. You can also set a default state model type of the parameterized type T, which can assist with ensuring the type safety of referring to your state in your application. The state token is declared as follows:
Or if you choose to not expose the model of your state class to the rest of the application then you can pass the type as unknown or any (this is useful if you want to keep all knowledge of the structure of your state class model private).
If you use pass this token as the name property in your @State declaration (or if the path specified matches your name property then you can use this token to refer to this state class from other parts of your application (in your selectors, or in plugins like the storage plugin that need to refer to a state class). The token can be used in your @State declaration as follows:
exportinterfaceTodoStateModel { title:string; completed:boolean;}exportconstTODOS_STATE_TOKEN=newStateToken<TodoStateModel[]>('todos');// Note: the @State model type is inferred from in your token.@State({ name:TODOS_STATE_TOKEN, defaults: []})@Injectable()exportclassTodosState {// ...}
A state token with a model type provided can be used in other parts of your application to improve type safety in the following aspects:
Improved type checking for @State, @Selector in a state class
exportinterfaceTodoStateModel { title:string; completed:boolean;}exportconstTODOS_STATE_TOKEN=newStateToken<TodoStateModel[]>('todos');@State({ name:TODOS_STATE_TOKEN, defaults: [] // if you specify the wrong state type, will be a compilation error})@Injectable()exportclassTodosState { @Selector([TODOS_STATE_TOKEN]) // if you specify the wrong state type, will be a compilation errorstaticgetCompletedList(state:TodoStateModel[]):TodoStateModel[] {returnstate.filter(todo =>todo.completed); }}
The following code demonstrates mismatched types that will be picked up as compilation errors:
exportconstTODOS_STATE_TOKEN=newStateToken<TodoStateModel[]>('todos');@State({ name:TODOS_STATE_TOKEN, defaults: {} // compilation error - array was expected, inferred from the token type})@Injectable()exportclassTodosState { @Selector([TODOS_STATE_TOKEN]) // compilation error - TodoStateModel[] does not match string[]staticgetCompletedList(state:string[]):string[] {return state; }}
Improved type inference for store.selectSignal, store.select, store.selectOnce, store.selectSnapshot
@Component(/**/)classAppComponentimplementsOnInit {constructor(private store:Store) {}ngOnInit():void {consttodosSignal=this.store.selectSignal(TODOS_STATE_TOKEN); // infers type Signal<TodoStateModel[]>consttodos=this.store.selectSnaphot(TODOS_STATE_TOKEN); // infers type TodoStateModel[]consttodos$=this.store.select(TODOS_STATE_TOKEN); // infers type Observable<TodoStateModel[]>constoneTodos$=this.store.selectOnce(TODOS_STATE_TOKEN); // infers type Observable<TodoStateModel[]> }}