Skip to content
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

Signal store feature required methods not working #4690

Closed
1 task
EthanSK opened this issue Jan 28, 2025 · 6 comments
Closed
1 task

Signal store feature required methods not working #4690

EthanSK opened this issue Jan 28, 2025 · 6 comments

Comments

@EthanSK
Copy link

EthanSK commented Jan 28, 2025

Which @ngrx/* package(s) are the source of the bug?

signals

Minimal reproduction of the bug/regression with instructions

https://stackblitz.com/edit/github-goablmzw-zqaqtxa3?file=src%2Fmain.ts

when withSomeRandoOtherFeature is uncommented, regardless of if before or after withMethod, it complains

Property 'hello' is missing in type '{}' but required in type '{ hello(): string; }'. [plugin angular-compiler]

even though hello is there in the withMethods in the feature it's declared

Expected behavior

Feature composition should work as such. I have provided the correct method, but it wont detect it.

Versions of NgRx, Angular, Node, affected browser(s) and operating system(s)

"dependencies": {
"@angular/animations": "~19.0.0",
"@angular/cdk": "~19.0.2",
"@angular/common": "~19.0.0",
"@angular/compiler": "~19.0.0",
"@angular/core": "~19.0.0",
"@angular/fire": "19.0.0-rc.5",
"@angular/forms": "~19.0.0",
"@angular/material": "~19.0.2",
"@angular/platform-browser": "~19.0.0",
"@angular/platform-browser-dynamic": "~19.0.0",
"@angular/platform-server": "~19.0.0",
"@angular/router": "~19.0.0",
"@angular/ssr": "~19.0.0",
"@floating-ui/dom": "^1.6.13",
"@nestjs/axios": "^3.1.3",
"@nestjs/common": "^10.0.2",
"@nestjs/core": "^10.0.2",
"@nestjs/platform-express": "^10.0.2",
"@nestjs/swagger": "^8.1.0",
"@ngrx/operators": "^19.0.0",
"@ngrx/signals": "^19.0.0",
"app-root-path": "^3.1.0",
"axios": "^1.7.9",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"copy-webpack-plugin": "^12.0.2",
"depcheck": "^1.4.7",
"express": "~4.18.2",
"firebase": "^11.0.2",
"firebase-admin": "^13.0.1",
"firebase-functions": "^6.2.0",
"firebaseui": "^6.1.0",
"firebaseui-angular": "^6.3.0",
"fs-extra": "^11.2.0",
"lodash": "^4.17.21",
"nanoid": "^3.3.4",
"ngx-device-detector": "^9.0.0",
"ngx-float-ui": "^19.0.1",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.0",
"source-map-support": "^0.5.21",
"spotify-uri": "^4.1.0",
"stripe": "^17.4.0",
"zone.js": "~0.15.0"

macos latest

Other information

No response

I would be willing to submit a PR to fix this issue

  • Yes
  • [x ] No
@EthanSK EthanSK changed the title Signal store feature required methods not worknig Signal store feature required methods not working Jan 28, 2025
@rainerhahnekamp
Copy link
Contributor

Nested Features with both having Input constraints... That's an interesting one. I've added one variation to it.

The nested feature withPrint works because it get the Input from the signalStore. The nested featurewithDoublePrint fails because it requires the double from the feature withDouble.

function withDouble() {
  return signalStoreFeature(
    type<{ state: { value: number } }>(),
    withComputed((state) => ({
      double: computed(() => state.value() * 2),
    })),
    withPrint(),
    withDoublePrint()
  );
}

function withPrint() {
  return signalStoreFeature(
    type<{ state: { value: number } }>(),
    withMethods((store) => ({
      print() {
        console.log(store.value());
      },
    }))
  );
}

function withDoublePrint() {
  return signalStoreFeature(
    type<{ props: { double: Signal<number> } }>(),
    withMethods((store) => ({
      printDouble() {
        console.log(store.double());
      },
    }))
  );
}

@EthanSK
Copy link
Author

EthanSK commented Jan 29, 2025

I'm not sure the example you responded with is the same as the issue i'm having? My example is still a direct chain of dependencies, but anyway it might be the same core problem as your example

The reason I'm using features in the first place is to just break out my store into subsections to avoid a monolith, hence using features.

I have a method that needs to be used in the parent feature and child feature, to avoid duplication. I ideally don't want to have to inject a separate service, as that would go against the pattern i've been using so far of defining the methods in the feature directly.

I think this is an elegant approach but is currently impossible due to this bug.

@markostanimirovic
Copy link
Member

The first compilation error is expected - withSomeRandoOtherFeature expects the hello method to be defined before it's called, but the method is defined after:

Image

When it comes to the compilation error that happens when withSomeRandoOtherFeature is called after the hello method is defined - this is a known TypeScript limitation that is described in the official documentation: https://ngrx.io/guide/signals/signal-store/custom-store-features#known-typescript-issues

To solve it, it's necessary to define an unused generic for each feature with expected input:

Image

Playground link with applied fixes: https://stackblitz.com/edit/github-goablmzw-lqssxjyk?file=src%2Fmain.ts

@rainerhahnekamp
Copy link
Contributor

this is a known TypeScript limitation

Ouch, should have seen that one...

@EthanSK
Copy link
Author

EthanSK commented Feb 3, 2025

ok but withSomeRandoOtherFeature(), doesnt work whe placed before the withMethods, which I actually need, because when I put it after in my code I get loads of errors

@markostanimirovic

@markostanimirovic
Copy link
Member

withSomeRandomOtherFeature from your example expects the hello method to be defined before the feature is used. This is what you defined in the example - withSomeRandomOtherFeature has the hello method as input. How would withSomeRandomOtherFeature be aware of the hello method, if the method is added to the SignalStore after the feature?

For more info, check the documentation of custom features with input: https://ngrx.io/guide/signals/signal-store/custom-store-features#creating-a-custom-feature-with-input

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants