@types/express package and had problems.Definitions by: in index.d.ts) so they can respond.I'm trying to create an Express app the way I used to in JS and it worked, but it doesn't work in TypeScript because express() doesn't create an http.Server:
import * as http from "http";
import express = require("express");
export default class TestClass {
public static init() {
const app = express();
app.use(...);
let server = http.createServer(app);
return server;
}
}
I need to do it this way because I don't want to listen immediately, I just want to set up the server and listen later. How can I get this to work? Do the typings need changing? Apparently, express() does return an http.Server because passing that in works in JavaScript.
This happens to me too.
Me too!
I think the @types/express package is broken currently (it's not directly maintained by expressjs). Try this:
let app: any;
app = express();
...
var server = http.createServer(app);
This doesn't use the strict typing typescript lets you do, but it's a temporary workaround that has worked for me.
Kind of sucks that it isn't maintained.
It should to be fine, something must have gone wrong.
Actually it's an Open Source. Here WE must fix it. Anyone can tell me what's exactly wrong in types?
@slawiko I'm not exactly sure whats wrong, but this may help; This is the type app should be:
let app: express.Application;
but for whatever reason this type can't be passed into http.createServer(app);. So I assume something in express.Application isn't defined correctly.
The problem is that http.createServer wants to be passed a (request: IncomingMessage, response: ServerResponse) => void. The object created by Express() does provide this:
export interface Express extends Application {
request: Request;
response: Response;
}
export interface Application extends IRouter, Express.Application {
/**
* Express instance itself is a request handler, which could be invoked without
* third argument.
*/
(req: Request, res: Response): any;
[...]
However, Request implements more too, such as:
set(setting: string, val: any): Application;
get: ((name: string) => any) & IRouterMatcher<this>;
Because this is not implemented by IncomingMessage, TypeScript says you can't assign the Express object to the required http.createServer function signature (which seems odd; why is there a problem implementing more than is necessary?) so you get errors like Property 'get' is missing in type 'IncomingMessage'..
You can get it to work by casting it to something compatible:
_server = http.createServer(webApp as (req: any, res: any) => void);
But this feels clunky/hacky; it's just basically saying to TypeScript "it works, just believe me god dammit!!". There should be a more elegant way to do it so it fits in nicely with the Express typings. Perhaps the IncomingMessage and ServerResponse arguments in the function signature should be interfaces rather than references to classes? Then those interfaces could actually be implemented by Express and I think that would work. Someone more au fait with the intricacies of TypeScript needs to advise on this... @andy-ms ? :smile:
The compiler is behaving correctly -- req: Request occurs in an in position, so it's contravariant. Application declares that it needs to be passed a full Request with all of its properties, which is incompatible with something that could work with only getting an IncomingMessage.
One solution would be to change Application to take only an IncomingMessage -- if that's accurate to what the library can actually do.
@andy-ms I thought arguments were bivariant in TS?
Not with --strictFunctionTypes.
I made a PR to fix this when --strictFunctionTypes is used. But I'm not _that_ familiar with express, so please comment if this change is correct or not. https://github.com/DefinitelyTyped/DefinitelyTyped/pull/21643
@donaldpipowitch it fixes problem for me, but I'm not sure, that it won't break something. Let's ask any expert. Anyway, thank you!
Most helpful comment
This happens to me too.