In my small project, I want to build a BabyCam that can be accessed from any web browser using a Raspberry Pi Zero. For this, I would like to open a web socket using express-is to stream video to several clients. I am basing most of the video-related code on the raspivid-stream module. However, when trying to access the web socket, I get a type error for app.ws(...
stating Property 'ws' does not exist on type 'Application'
. Of course, I imported both the typings for express and express-ws.
I am not really sure, what the problem is as the same call in JavaScript appears work fine. Here's the code - I am glad for any help!
import express from 'express';
import { Request, Response } from 'express';
import fs from 'fs';
import https from 'https';
import http from 'http';
import raspividStream from 'raspivid-stream';
import expressWs from 'express-ws';
const server: express.Application = express();
const httpPort: number = 8080;
const httpsPort: number = 8443;
const sslCredentials = {
key: fs.readFileSync('../ssl/localhost.key', 'utf8'),
cert: fs.readFileSync('../ssl/localhost.cert', 'utf8')
};
// CREATE SERVER
const httpServer = http.createServer(server);
const httpsServer = https.createServer(sslCredentials, server);
expressWs(server, httpsServer);
// ROUTES
server.get('*', (req: Request, res:Response) => {
if (!req.secure) {
return res.redirect(`https://${req.hostname}:${httpsPort}${req.originalUrl}`);
}
res.sendFile(__dirname + '/client/index.html');
});
// WEBSOCKET
server.ws('/video-stream', (ws) => {
console.log('Client connected');
ws.send(JSON.stringify({
action: 'init',
width: '960',
height: '540'
}));
var videoStream = raspividStream({ rotation: 180 });
videoStream.on('data', (data) => {
ws.send(data, { binary: true }, (error) => { if (error) console.error(error); });
});
ws.on('close', () => {
console.log('Client left');
videoStream.removeAllListeners('data');
});
});
// START SERVER
httpServer.listen(httpPort, () => {
console.log(`BabyCam (redirect) listening at http://localhost:${httpPort}/`);
});
httpsServer.listen(httpsPort, () => {
console.log(`BabyCam (SSL) listening at https://localhost:${httpsPort}/`);
});
Property 'ws' does not exist on type 'Application'
is a typescript error, indicating that typescript is not aware of a ws()
method on app
. This is expected because ws()
is not a part of the default express
API, and so the TS types (@types/express
) don't define it.
The ws()
method comes from the express-ws
module as a "mix in". The express-ws
types (@types/ws-express
) do define this, but the code needs to be structured to allow Typescript to be aware of this ...
First, make sure you have TS types for express
and express-ws
installed:
npm install @types/express @types/express-ws
Then create server
as follows:
const expressServer = express(); // Type = Express
const wsServer = expressWs(expressServer); // Type = expressWs.Instance
const server = wsServer.app; // type = wsExpress.Application
Defining the code in this way gives server
the expressWs.Application type, defined here (which includes the WithWebsocketMethod
declaration for ws()
here)
NOTE: The runtime value of server
and expressServer
is identical at runtime. It's the same exact Express instance (which is why your code works fine when run as plain JS). We're just handling things slightly differently to keep Typescript informed of what's happening with the types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With