What is the best way to implement strong typing for a socketIO server in TypeScript?

Is there a way to properly type the private property private io in Typescript to prevent the error message Property 'io' has no initializer and is not definitely assigned in the constructor

import fastify, { FastifyReply, FastifyRequest } from "fastify";
import socketIO from "socket.io";
import fastifysocketIO from "fastify-socket.io";
import fastifyStatic from "fastify-static";
import path from "path"



class App {
    private server;
    private port: number;
    private io: socketIO.Server;

    constructor(port: number) {
        this.server = fastify({ logger: true });
        this.port = port;
        this.server.register(fastifyStatic, {

            root: path.join(__dirname, "../public"),
        });
        this.server.register(fastifysocketIO, ({
            cors: { origin: "*" }
        }));

        this.server.ready(err => {
            if (err) { throw err }
            this.io = this.server.io;

            this.io.on('connect', (socket: socketIO.Socket) => {
                return console.info('Socket connected!', socket.id);
            })
        });

        this.server.get("/", (request: FastifyRequest, reply: FastifyReply) => {
            reply.sendFile("chat.html");
        })
    }
    public start() {
        this.server.listen(this.port);

    }
}
new App(3000).start();

Answer №1

When you set .io in a callback, it may happen after the server has already started. There are 3 options you can consider:

Option 1: Ignore the error

If you define your property as:

private io!: socketIO.Server;

This essentially tells Typescript that you acknowledge not setting this property during construction but assure that everything will work fine.

Just remember, there is a brief period between constructing your App class and the ready callback where this.io remains undefined.

Option 2: Accurately type

You have the choice to modify the definition to:

private io: socketIO.Server | null = null;

This enforces every usage of this.io to first verify that it's initialized.

Option 3: Set up everything before construction

In simple terms, you can also create your Server and IO objects externally from the class and then pass them as arguments in the constructor.

One thing worth noting is that many people tend to write Javascript as they would in languages like Java or PHP, even when unnecessary.

Classes should be used judiciously in Javascript with a clear purpose. If they involve an 'evolving state' like this, typing with Typescript can become more challenging.

If this code snippet represents your entire class, some might argue that it doesn't really need to be a class at all.

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

Generating an array of strings that is populated within the Promise handler

If I come across code like this in my Ionic/Angular/TypeScript project... let arr: Array<string> = []; this.databaseProvider.getAllSpecies().then(allSpecies => { for(let species of allSpecies) { if(species.name.toLowerCase().indexOf(keyword ...

Jest: A guide on mocking esModule methods

In my code, I have a function that utilizes the library jszip to zip folders and files: // app.ts const runJszip = async (): Promise<void> => { const zip = new Jszip(); zip.folder('folder')?.file('file.txt', 'just som ...

Jaydata is a powerful open source library for interacting with databases

I rely on jaysvcutil for compiling OData $metadata and generating JayDataContext.js, which is truly impressive. However, I prefer to work with Typescript without using import/export syntax or other third-party tools like requirejs or systemjs. Even thoug ...

Is it possible to utilize an npm package in TypeScript without a d.ts definition file?

Is it possible to use an npm package in TypeScript and Node.js without a .d.ts definition file? If so, how can I make it work? Currently, my code looks like this and I'm getting an error that says "cannot find module 'node-rest-client'" bec ...

Discover the step-by-step process for moving data between collections in MongoDB

I am currently working on nestjs and have two collections, one for orders and the other for payments. My goal is to retrieve a single entry from the orders collection and save that same entry into the payments collection. Below is the code for the service ...

Guide to automatically installing @types for all node modules

As a newcomer to Typescript and NodeJs, I have been experiencing errors when mentioning node modules in my package.json file and trying to import them. The error messages I always encounter are as follows: Could not find a declaration file for module &apos ...

Transform a struggling Observable into a successful one

When working with an HTTP service that returns an observable, I encountered an error during the subscribe process for a specific use case that I would like to address within the successful path. My scenario looks like this: In my service class: class My ...

Is there a way to retrieve the attributes of a generic object using an index in TypeScript?

I'm currently working on a function that loops through all the attributes of an object and converts ISO strings to Dates: function findAndConvertDates<T>(objectWithStringDates: T): T { for (let key in Object.keys(objectWithStringDates)) { ...

Angular: Tailoring the Context Menu

Currently, I am utilizing a helpful tutorial to implement a custom context menu feature. The main issue I am facing is that when a user interacts with the list items, I want the correct index of each item to be displayed. However, at the moment, clicking o ...

Is there a way to dynamically exclude files from the TypeScript compiler?

Currently, I am in the process of setting up a node/typescript server for a real-time application. Both my server and client are located within the same folder. My goal is to exclude "src/client" from the typescript compiler when executing the "server:dev ...

Issue: Transition of FCM to HTTP v1 API from Previous Legacy API

Recently, I have been working on migrating FCM from the legacy API to the HTTP V1 API. Here's a comparison of the "working code before" and after the necessary modifications: Before: const payload = { data: ...

Angular is not able to access the value of a promise in a different function after it has been retrieved

I have a form with default values that should be added to the form fields when it appears. There are two functions: #1 for fetching data from the backend and #2 for displaying the form: person$: any; ngOnInit() { this.getPersonData(123) this.buildPer ...

Troubleshooting the error message: "Uncaught TypeError: this.schedulerActionCtor is not a constructor" that occurs while executing the rootEpic in redux-

As I delve into learning how redux-observables work with typescript, I've been following a project example and referencing various guides like those found here and here. However, no matter what I try in setting up the epics/middleware, I keep encounte ...

Is it recommended to exclude the NGXS NgxsLoggerPluginModule for production deployments?

When developing, it's common to use the following imports: import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin'; import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin'; Is it recommended to remove these imp ...

Tips for resolving logical errors in Angular's if statements

I have a straightforward logic with conditions written, but I am always getting inaccurate results. I am dealing with three fields: immediate limit, hold limit, and LDC. The condition I am trying to implement is that when the immediate limit and hold limit ...

Does this Spread Operator Usage Check Out?

Upon reviewing Angular's API documentation, I came across the declaration for the clone() method in HttpRequest as follows: clone(update: { headers?: HttpHeaders; reportProgress?: boolean; params?: HttpParams; responseType?: "arraybuffer" ...

Is it feasible to restrict generic classes for particular functions?

Imagine creating a customized container in TypeScript. Let's consider this straightforward example: class Container<T> { val: T; constructor(t: T) { this.val = t; } } Now, let's say you want to implement a function that can gene ...

Creating a versatile function in TypeScript for performing the OR operation: A step-by-step guide

Is there a way in TypeScript to create a function that can perform an OR operation for any number of arguments passed? I currently have a function that works for 2 arguments. However, I need to make it work for any number of arguments. export const perfo ...

I possess an item that I must display its title as a <choice> in a <menu> while returning a different variable

I am working with an object: company: { name: 'Google', id: '123asd890jio345mcn', } My goal is to display the company name as an option in a material-ui selector (Autocomplete with TextField rendering). However, when a user selects ...

How to make an input blur in Angular 2 when a button is clicked?

Is there a way to blur an input field by pressing the return button on a mobile native keyboard? Here is an example: <input type="text" #search> this.search.blur() //-- unfocus and hide keyboard ...