Gabriel
Gabriel

Reputation: 989

Using ngrx signal store with index signatures in state

I am trying to use an index signature for keys in my data model with NgRx Signal Store.

My problem is that each time I am trying to access a key, I get an Element implicitly has an 'any' type error.

In the example below, I am trying to access the 'abc' key in the template.

import { Component, inject } from '@angular/core';
import { signalStore, withState } from '@ngrx/signals';

export type MyState = { [key: string]: string };

const initialState: MyState = { abc: 'test' };

export const MyStore = signalStore(
  { providedIn: 'root' },
  withState(initialState),
);

@Component({
  selector: 'app-root',
  template: `<p>{{ myStore['abc']() }}</p>`,
})
export class AppComponent {
  myStore = inject(MyStore);
}

And here is the exact error:

[ERROR] NG3: Element implicitly has an 'any' type because expression of type '"abc"' can't be used to index type '{} & StateSource<{ [x: string]: string; }>'.
  Property 'abc' does not exist on type '{} & StateSource<{ [x: string]: string; }>'. [plugin angular-compiler]

Is there a way to make index signatures work with ngrx signal store? Or am I supposed to stick with ngrx entities?

Upvotes: 1

Views: 90

Answers (1)

Naren Murali
Naren Murali

Reputation: 57696

You can define the interface for the signal, inbetween the signal store function withState:

export const MyStore = signalStore<SignalStoreFeatureResult>(
  { providedIn: 'root' },
  withState<MyState>(initialState)
);

Full Code:

import { Component, inject } from '@angular/core';
import {
  signalStore,
  SignalStoreFeatureResult,
  withState,
} from '@ngrx/signals';
import { bootstrapApplication } from '@angular/platform-browser';

export type MyState = { [key: string]: string };

const initialState: MyState = { abc: 'test' };

export const MyStore = signalStore<SignalStoreFeatureResult>(
  { providedIn: 'root' },
  withState<MyState>(initialState)
);

@Component({
  selector: 'app-root',
  template: `<p>{{ myStore['abc']() }}</p>`,
  providers: [MyStore],
})
export class AppComponent {
  myStore = inject(MyStore);

  ngOnInit() {
    console.log(this.myStore['abc']);
  }
}

bootstrapApplication(AppComponent);

Stackblitz Demo

Upvotes: 0

Related Questions