[x] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
consider the following snippet
export interface RouterStateUrl {
url: string;
queryParams: Params;
params: Params;
}
export interface RootState {
router: RouterReducerState<RouterStateUrl>;
}
export const reducers: ActionReducerMap<RootState> = {
router: routerReducer
};
tsconfig.json:
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"skipLibCheck": true,
"noUnusedParameters": true,
"noUnusedLocals": true,
"strict": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2016",
"dom"
]
}
}
Do note that
strict: true
It worked with typescript 2.5.3, but after updating to typescript 2.6.2 (which is now supported in angular 5.2.0), compiler has show an error and project can not be successfully built anymore
Error:(22, 14) TS2322: Type '{ router: <T = RouterStateSnapshot>(state: RouterReducerState<T>, action: RouterAction<any, Route...' is not assignable to type 'ActionReducerMap<RootState, Action>'.
Types of property 'router' are incompatible.
Type '<T = RouterStateSnapshot>(state: RouterReducerState<T>, action: RouterAction<any, RouterStateSnap...' is not assignable to type 'ActionReducer<RouterReducerState<RouterStateUrl>, Action>'.
Types of parameters 'state' and 'state' are incompatible.
Type 'RouterReducerState<RouterStateUrl> | undefined' is not assignable to type 'RouterReducerState<RouterStateUrl>'.
Type 'undefined' is not assignable to type 'RouterReducerState<RouterStateUrl>'.
App continue to work with typescript 2.6.2
clone this repo ngrx-bug-report and serve --aot
git clone https://github.com/sandangel/ngrx-bug-report.git
ng serve --aot
Chrome 63, Ubuntu 16.04, npm 5.6, node 8.9.4, ngrx 4.1.1
Confirming, i have this problem, too!
iI you use
"typescript": "~2.5.3" along with angular 5.2 it works again.
seem like typescript 2.6.2 break many other libs, switched back to 2.5.3 now
@sandangel It looks like this error is displaying when strictFunctionTypes is set to true. Can you confirm by setting strict to false and just enabling strictFunctionTypes?
I confirm that it work when set strict to true and strictFunctionTypes to false
@brandonroberts @MikeRyanDev this is not only problem of the router, but basically with approach of typed actions.
If you bump angular, install typescript ^2.6 and add "strictFunctionTypes": true, to platform/example-app/tsconfig.app.json.
Then yarn run example:start will not compile and will give a lot of errors.
See: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html
I confirm that I run into the same problem of type incompatibility, and I also have created an issue (https://github.com/ngrx/platform/issues/611#issuecomment-357678473) that is unanswered.
I don't agree to the fact that we need to set "strictFunctionTypes": false to compile properly.
IMHO that flag unsets a benefit we can get from the compiler... and ngRx should not require that.
I have modified ofType implementation and solved error in effects. Then using REDUCER_TOKEN instead of ActionReducerMapp as a work around.
import { Action } from '@ngrx/store';
import { filter } from 'rxjs/operators';
export function ofType<T extends Action>(...allowedTypes: string[]) {
return filter((action: Action): action is T => {
return allowedTypes.some(type => type === action.type);
});
}
export const REDUCER_TOKEN = new InjectionToken<ActionReducerMap<State>>('Registered Reducers');
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule.withServerTransition({ appId: 'my-app' }),
BrowserAnimationsModule,
LayoutModule,
MaterialModule,
SharedModule,
RouterModule.forRoot([]),
ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }),
/* use token here */
StoreModule.forRoot(REDUCER_TOKEN),
EffectsModule.forRoot([RouterEffects]),
!environment.production ? StoreDevtoolsModule.instrument() : [],
StoreRouterConnectingModule.forRoot({
stateKey: 'router'
})
],
bootstrap: [AppComponent],
providers: [
{ provide: RouterStateSerializer, useClass: CustomSerializer },
// Provide reducer map here
{ provide: REDUCER_TOKEN, useFactory: () => ({ router: routerReducer }) }
]
})
export class AppModule {}
Or you can use ActionReducerMap
hi, I still have this problem and I suppose that this issue was not fixed by #841
The source of error is the contravariantly check in ts 2.6 with ActionReducer type and routerReducer type:
export interface ActionReducer<T, V extends Action = Action> {
(state: T | undefined, action: V): T;
}
// and
export declare function routerReducer<T = RouterStateSnapshot>(
state: RouterReducerState<T>,
action: RouterAction<any, T>
): RouterReducerState<T>;
Contravariance in the argument type means A <: B implies (B -> T) <: (A -> T) (A and B flipped sides).
which mean:
both are not possible since undefined is not assignable to RouterReducerState
I suggest to fix this issue we have to change the signature of routerReducer to
export declare function routerReducer<T = RouterStateSnapshot>(
state: RouterReducerState<T> | undefined, // add undefined
action: RouterAction<any, T>
): RouterReducerState<T>;
and change the default type in ActionReducerMap<T, V = Action> to ActionReducerMap<T, V = any>;
Most helpful comment
@brandonroberts @MikeRyanDev this is not only problem of the router, but basically with approach of typed actions.
If you bump angular, install typescript
^2.6and add"strictFunctionTypes": true,toplatform/example-app/tsconfig.app.json.Then
yarn run example:startwill not compile and will give a lot of errors.See: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html