Universal: Engine setup error in argument type

Created on 25 Jul 2019  路  17Comments  路  Source: angular/universal

Bug Report

What is the expected behavior?

Engine setup should work as expected

What is the current behavior?

Error in app.engine (), is it an issue with versions?

Argument of type '(filePath: string, options: RenderOptions, callback: (err?: Error | null | undefined, html?: string | undefined) => void) => void' is not assignable to parameter of type '(path: string, options: object, callback: (e: any, rendered: string) => void) => void'.
Types of parameters 'callback' and 'callback' are incompatible.
Types of parameters 'rendered' and 'html' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.ts(2345)`

Preview of my server.ts

const app = express();
const PORT = process.env.PORT || 4001;
const DIST_FOLDER = join(process.cwd(), 'wwwroot', 'browser');
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./wwwroot/server/main');
//Error is here
app.engine(
  'html',
  ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [provideModuleMap(LAZY_MODULE_MAP)]
  })
);
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);

What modules are related to this issue?

- [ ] aspnetcore-engine
- [ ] common
- [x ] express-engine
- [ ] hapi-engine
- [ ] module-map-ngfactory-loader

Environment:

Output from: ng --version.
Angular CLI: 7.0.6
Node: 8.14.0
OS: win32 x64
Angular:
... animations, cdk, cli, common, compiler, compiler-cli, core
... flex-layout, forms, http, language-service, material
... platform-browser, platform-browser-dynamic, platform-server
... router, service-worker

Package Version

@angular-devkit/architect 0.10.6 (cli-only)
@angular-devkit/build-angular
@angular-devkit/core 7.0.6 (cli-only)
@angular-devkit/schematics 7.0.6 (cli-only)
@schematics/angular 7.0.6 (cli-only)
@schematics/update 0.10.6 (cli-only)
rxjs 6.5.2
typescript 3.1.6
webpack 4.29.0

Preview of my package.json

 "dependencies": {
    "@angular/animations": "^7.1.4",
    "@angular/cdk": "^7.0.4",
    "@angular/common": "^7.0.4",
    "@angular/compiler": "^7.0.4",
    "@angular/core": "^7.0.4",
    "@angular/flex-layout": "^7.0.0-beta.24",
    "@angular/forms": "^7.0.4",
    "@angular/http": "^7.0.4",
    "@angular/material": "^7.0.4",
    "@angular/platform-browser": "^7.0.4",
    "@angular/platform-browser-dynamic": "^7.0.4",
    "@angular/platform-server": "^7.1.4",
    "@angular/router": "^7.0.4",
    "@angular/service-worker": "^7.0.4",
    "@netbasal/ngx-content-loader": "2.1.0",
    "@nguniversal/express-engine": "7.0.2",
    "@nguniversal/module-map-ngfactory-loader": "v7.0.2",
    "@ngx-translate/core": "11.0.1",
    "@ngx-translate/http-loader": "4.0.0",
  }
repro steps

Most helpful comment

@alan-agius4 here are the steps that reproduce the error using the Angular CLI and following the documentation for adding Angular Universal:

$ ng new TestAngularUniversal --defaults=true --strict=true
$ cd TestAngularUniversal
$ ng add @nguniversal/express-engine
$ npm run build:ssr && npm run serve:ssr

The relevant error output is:

ERROR in server.ts:18:25 - error TS2345: Argument of type '(filePath: string, options: Readonly<RenderOptions>, callback: (err?: Error | null | undefined, html?: string | undefined) => void) => void' is not assignable to parameter of type '(path: string, options: object, callback: (e: any, rendered: string) => void) => void'.
  Types of parameters 'callback' and 'callback' are incompatible.
    Types of parameters 'rendered' and 'html' are incompatible.
      Type 'string | undefined' is not assignable to type 'string'.
        Type 'undefined' is not assignable to type 'string'.

18   server.engine('html', ngExpressEngine({
                           ~~~~~~~~~~~~~~~~~
19     bootstrap: AppServerModule,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20   }));
   ~~~~

All 17 comments

Facing the same problem

@free-easy do you have a service worker in your application ?

No. I work-arounded the issue by uninstalling @types/express. Probably there is something more clever to do, like telling tsc to ignore some type definition when build something...

have u solved this issue ? @DMZakaria

@waseem-isaac-BBN In my case, it was an issue with my service worker

Hi - Is this still an issue? Can someone share a small repro?

I started getting this when upgrading to angular 9. A bad workaround is to force the import as "any" const ngExpressEngine: any = require("@nguniversal/express-engine");

I fixed this in kind of a clunky way by introducing a function with the expected type:

const engine: (filePath: string, options: Readonly<RenderOptions>, callback: (err?: Error | null | undefined, html?: string | undefined) => void) => void = ngExpressEngine({
    bootstrap: AppServerModule,
  });

  let engineFunc = (path: string, options: object, callback: (e: any, rendered: string) => void): void => {
    engine(path, options as Readonly<RenderOptions>, callback);
  };

  server.engine('html', engineFunc);

It will require you to add an import for RenderOptions from @nguniversal/express-engine.

I also encountered this after upgrading to angular 9, my workaround is similar to @bufke .

  server.engine(
    'html',
    ngExpressEngine({
      bootstrap: AppServerModule
    }) as any
  );

hope there is a more elegant way.

Can someone please provide a reproduction thanks?

@alan-agius4 here are the steps that reproduce the error using the Angular CLI and following the documentation for adding Angular Universal:

$ ng new TestAngularUniversal --defaults=true --strict=true
$ cd TestAngularUniversal
$ ng add @nguniversal/express-engine
$ npm run build:ssr && npm run serve:ssr

The relevant error output is:

ERROR in server.ts:18:25 - error TS2345: Argument of type '(filePath: string, options: Readonly<RenderOptions>, callback: (err?: Error | null | undefined, html?: string | undefined) => void) => void' is not assignable to parameter of type '(path: string, options: object, callback: (e: any, rendered: string) => void) => void'.
  Types of parameters 'callback' and 'callback' are incompatible.
    Types of parameters 'rendered' and 'html' are incompatible.
      Type 'string | undefined' is not assignable to type 'string'.
        Type 'undefined' is not assignable to type 'string'.

18   server.engine('html', ngExpressEngine({
                           ~~~~~~~~~~~~~~~~~
19     bootstrap: AppServerModule,
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20   }));
   ~~~~

Getting the same error after following pretty much same commands with same --strict=true flag. However, when I recreated the same project without the flag, the npm run build:ssr and npm run dev:ssr commands succeeded just fine. So seems to be something regarding the --strict=true flag and Angular 9?

I also ran into similar problem while using npm run dev:ssr . Earlier while using npm lint and it was showing typedef errors in server.ts file for functions app and run.
Although it worked fine after using any as described by @bufke and @blinkcat.

@bskeen @rts-cwalker
I got the same error. It is strict mode when --strict flag is set. Fix to work arround:

export function app(): express.Application { // --> this function return server and must change return type to express.Application. this is explanation for last line of this function.
  const server: express.Application = express();
  const distFolder = join(process.cwd(), 'dist/PROJECT_NAME/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }) as (path: string, options: object) => void); // --> add here. because typeof engine function and return type ngExpressEngine is not match. reassign type for it

  server.set('view engine', 'html');
  server.set('views', distFolder);

  // Example Express Rest API endpoints
  // server.get('/api/**', (req, res) => { });
  // Serve static files from /browser
  server.get('*.*', express.static(distFolder, {
    maxAge: '1y'
  }));

  // All regular routes use the Universal engine
  server.get('*', (req, res) => {
    res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
  });

  return server;
}

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}) as (path: string, options: object) => void);

Thank you @tuananhitoct, this solved my problem.

The above should no longer be a problem with the @nguniversal/express-engine version 10.0.2

If the problem persists after upgrading, please open a new issue, provide a simple repository reproducing the problem, and describe the difference between the expected and current behavior.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings