Encounter a Typescript error when dealing with "app.ws" while using express-ws

I have a small project in mind where I want to create a BabyCam that can be accessed from any web browser using a Raspberry Pi Zero. My plan is to set up a web socket using express-is to stream video to multiple clients. I'm utilizing the raspivid-stream module for most of the video-related code. However, when attempting to access the web socket, I encounter a type error related to app.ws(..., specifically stating

Property 'ws' does not exist on type 'Application'
. I've made sure to import the typings for both express and express-ws.

I'm somewhat confused as to why this problem is occurring, especially since the same call works fine in JavaScript. Here's the code snippet - any help would be greatly appreciated!

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}/`);
});

Answer №1

Issue with 'ws' in type 'Application'
is an error specific to TypeScript, indicating that TypeScript does not recognize a method called ws() on the object app. This occurs because ws() is not part of the standard express API, and therefore the TypeScript types (@types/express) do not include it.

The ws() method is actually provided by the express-ws module as an add-on feature. The TypeScript types for express-ws (@types/ws-express) do define this method, but the code structure needs to be adjusted to ensure TypeScript recognizes it properly...

To address this issue, first make sure you have installed the TypeScript types for both express and express-ws:

npm install @types/express @types/express-ws

Next, create the server instance as shown below:

const expressServer = express();           // Type = Express 
const wsServer = expressWs(expressServer); // Type = expressWs.Instance
const server = wsServer.app;               // Type = wsExpress.Application

By defining the code in this manner, the variable server will now have the correct type of expressWs.Application, as specified here (which includes the declaration for ws() here).

It's important to note that the runtime value of server and expressServer remains the same. They both refer to the exact same Express instance (which explains why your code runs without issues when executed as regular JavaScript). The only difference lies in how TypeScript handles the type information.

Answer №2

The object Express.Application does not contain an attribute named ws, which is causing the error message to be displayed. In order to resolve this issue, you should utilize the result of expressWS(server, httpsServer) as the app variable that is accessible, typed as Express.Application & WithWebsocketMethod.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Incorporating fresh components and newly defined attributes in Angular

Is there a way for me to click on a new component button, specify a name, description, select type, and add attributes such as default value and type? I need all this information to be saved and for the new button to appear in the drag-and-drop section. ...

The compatibility between Typescript methods and event handlers is lacking

Consider this basic TypeScript script class foo { v: number = 1; public bar() { console.log(this.v); } } var a = new foo(); var b = new foo(); document.getElementById('test').addEventListener("click", a.bar); document.getE ...

Utilizing Think ORM seamlessly across multiple files without the need to repeatedly establish a connection to the

I'm facing a situation where I have numerous models for thinky, and in each file I am required to create a new object for thinky and connect it multiple times due to the high number of models. var dbconfig = require('../config/config.js')[& ...

Submitting an HTTP POST REQUEST with both an image and text

Is there a way to send an image with text from VueJs to an ExpressJs backend? I've currently implemented two HTTP POST requests for this process. Please note: "this.albumName" and "this.albumDesc" contain text, while the formData variable holds the ...

Navigating within components using code is an essential skill when working with Vue Router

I am currently developing a Quasar application powered by Vue 3 with vue-router version 4 All my routes are properly configured and function well when navigating from a component template using <router-link to="/route">Go to route</rout ...

React Native: Issue with the data section in FlatList

I encountered an issue while using Flatlist to address a problem, but I ran into an error with the data property of my Flatlist. The error message is not very clear and I'm having trouble understanding it ( No overload matches this call. Overload 1 of ...

Tips for resolving CORS error in swagger-ui-express

I'm encountering a "Possible cross-origin (CORS) issue?" error with Spec2 while running this swagger-ui-express application: const express = require('express'); var cors = require('cors'); const app = express(); const swaggerUi = ...

Deleting specialized object using useEffect hook

There's a simple vanilla JS component that should be triggered when an element is added to the DOM (componentDidMount) and destroyed when removed. Here's an example of such a component: class TestComponent { interval?: number; constructor() ...

update the value of a specific document in Firestore by specifying its

Is there a way to update document values in a Firestore collection for multiple records without manually specifying each document ID? Currently, I have a method that works for updating individual documents using their IDs, but what if I need to update a la ...

Parent component interacting with child component

In my application, I have a header component along with registration and login components. The selector of the header component is used in both the login and registration components. There is also a button in the header that displays as a login button if t ...

Error in Protractor Typescript: The 'By' type does not share any properties with the 'Locator' type

https://i.stack.imgur.com/8j2PR.png All the different versions Error. Protractor version : 5.2.0 npm : 3.10.10 node :6.9.5 typescript :2.6.0 The 'By' type does not share any properties with the 'Locator' type What is the solution to ...

Retrieve the username from a JSON Web Token in an Express application

I am working on a project that involves 3 different routes in my code - Users, Products, and Orders. Using jwt, I generate tokens for users and need to assign orders to token owners. Below is the Order Model I am using: var mongoose = require('mongoo ...

Strange behavior detected in TypeScript generic function when using a class as the generic parameter

class Class { } const f0 = <T extends typeof Class> (c:T): T => { return c } const call0 = f0 (Class) //ok const f1 = <T extends typeof Class> (c:T): T => { const a = new c() return a //TS2322: Type 'Class' is not assigna ...

Instructions on how to immediately terminate the function and send a response to the client without moving to the next callback

const handleLogin = (req, res) => { let user; User.findOne({ username: req.body.username }).then(_user => { if (!_user) { return res.status(401).json({ message: 'Username or password is inc ...

Is it possible to set up TypeScript npm packages to be installed in their original TypeScript format rather than JavaScript for the purpose of examining the source code?

Despite my lack of expertise in the inner workings of how a TypeScript library compiles itself to JavaScript before being placed in the node_modules directory, I have a question: Coming from a PHP background, I am accustomed to being able to explore any l ...

To validate any object, ensure that it contains a specific key before retrieving the corresponding value in typescript

When looking at a random object, my goal is to verify that it follows a certain structure. obj = {WHERE:{antherObject},OPTIONS{anotherObject}} Once I confirm the object has the key using hasProperty(key), how can I retrieve the value of the key? I thoug ...

I can't seem to get React Fetch and the expressJS post method to cooperate - what could I be overlooking?

I have been diving into the world of React and recently ventured into working with expressJS. However, I encountered an issue with the POST method as the data is not being successfully posted to the server. While I believe my fetching of the post method is ...

Unable to retrieve device UUID using capacitor/device on Android

I'm currently attempting to obtain the UUID of my devices so that I can send targeted notifications via Firebase. My front end and back end are connected, enabling the back end to send notifications to the front end using Firebase. However, all I am a ...

Problem with Infragistics radio button not firing change event when value is set manually

After migrating from Angular 11 to 17, I encountered a strange issue with my application's Infragistics radio button. The change event for the radio button does not trigger manually for the first time, but it works fine when changed through the applic ...

Sometimes the messages from a web socket (socket.io) seem to be non-existent, while other times they flood in all at once unpredictably

Every time I start my server, the web socket sends me 1 initial response with information about Bitcoin. However, I am facing an issue where I either do not receive updates when the price changes or suddenly receive a large number of updates all at once. I ...