-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Pre-initialized class fields with a TSConfig target set to ES2022 with useDefineForClassFields set to true will cause runtime issues #3654
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
Comments
I'd like to add another note on "Workaround" is that if you use |
This is true for anything that can be injected. Which is the case for NgRx. It won't erase the issue for non-injectable classes. |
FYI, there is an open ticket about this on microsoft/TypeScript#50971. When targeting |
TS team says that it works "as expected", so we'll need to add The current issue that TS is not highlighting it as an issue without the flag, and that will be fixed. |
The New applications using the Angular CLI will also have I think for starters the NGRX docs should be updated to be TC39 spec complaint so at least new users don’t write non complaint code. |
@alan-agius4 that seems like a pretty big ask across the entire Angular ecosystem, not just NgRx. We've discussed moving away from class-based grouping for effects but it wasn't prompted by this recent change. Feels like this should be handled by the compiler or somewhere else upstream and not the developer. |
With |
Right, got confused both outputs are spec compliant although now in the latest spec it has a different runtime behavior. |
It's as expected, but the compiler should error, like it does with the EsNext target. |
Nice to finally see some discussion, because when I raised a discussion about this issue it went unnoticed: #3405 Also I want to remind you all, that Angular 15 does not allow us to control “target” and “useDefinedForClassFields”: angular/angular-cli#23936 |
You can control |
It's nice that we can control “target” if the target is exactly ES2022 (because the only option left is “esnext” and you should not use it in prod).
|
The simplest workaround should be the following. We perform a general search and replace for both the demo and the schematics according to the following pattern:
BEFORE: @Injectable()
export class BookEffects {
loadBooks$ = createEffect(() => {
return this.actions$.pipe(
ofType(BookActions.loadBooks),
concatMap(() =>
/** An EMPTY observable only emits completion. Replace with your own observable API request */
EMPTY.pipe(
map(data => BookActions.loadBooksSuccess({ data })),
catchError(error => of(BookActions.loadBooksFailure({ error }))))
)
);
});
constructor(private actions$: Actions) {}
} AFTER: import { inject } from '@angular/core';
@Injectable()
export class BookEffects {
loadBooks$ = createEffect(() => {
inject(Actions).pipe(
ofType(BookActions.loadBooks),
concatMap(() =>
/** An EMPTY observable only emits completion. Replace with your own observable API request */
EMPTY.pipe(
map(data => BookActions.loadBooksSuccess({ data })),
catchError(error => of(BookActions.loadBooksFailure({ error }))))
)
);
});
} It has even fewer lines of code! 😎 |
Did not work for me :( |
Logic was in constructor before. Parameters injected in constructor are undefined when used in component class field initialization. Needed for use of latest JavaScript version (ES2022). See: ngrx/platform#3654
Closing this as resolved as it's handled by the framework migrations |
I still got this issue. how it resolved? |
solution: upgrade typescript: "typescript": "4.9.4" |
I would refactor the code to use |
this work fine for me |
using @Inject instead of constructor worked for me. |
using @Inject instead of constructor worked for me also |
fixing ngrx action$ not define issue in nx workspace
Uh oh!
There was an error while loading. Please reload this page.
Information
The Problem
Using TS with a TSConfig which has the
target
set toES2022
.When TS compiles code with this target, it aims to make it TC39 Compliant.
This introduces a runtime issue on modern browsers when we try to write classes that follow this pattern:
Following this pattern of initializing class properties by using a class property that is added via the constructor (
this.actions$
,this.store
) will throw runtime errors that these properties are not defined.Expected errors (listed in Browser Console):
Workarounds
There are currently two workarounds.
@Injectable
classes, use theinject()
functionuseDefineForClassFields
intsconfig.json
In your
tsconfig.json
(ortsconfig.app.json
in Nx Workspaces), set"useDefineForClassFields": false
in thecompilerOptions
.Example:
Notes
Existing applications that are migrated via the Angular CLI or Nx CLI will have
"useDefineForClassFields": false
set automatically.The text was updated successfully, but these errors were encountered: