Developing a TypeScript Library from Scratch

After following the instructions on this particular website, I have implemented the following JavaScript code:

function A(id) {
    var about = {
        Version: "0.0.0.1",
    };

    if (id) {
        if (window === this) {
            return new A(id);//<-Error in typescript
        }

        this.e = document.getElementById(id);
        return this;
    } else {
        return about;
    }
};

A.prototype = {
    doSomething: function () {
        //Implement some logic here
        return this;
    }
}

Example of JavaScript Usage:

var result = A("test");//The type of result should be 'A'
result = new A("test");//The type of result should be 'A'
result = A("test").doSomething();//The type of result should be 'A'
result = new A("test").doSomething();//The type of result should be 'A'

I am now interested in developing a library based on TypeScript that follows similar usage patterns. What would be the best approach to achieve this?

If I attempt to simply place this in a '.ts' file and compile, an error is generated stating: Error TS2350: Only a void function can be called with the 'new' keyword.

In addition, I am unsure of how to handle usage both with and without the 'new' keyword in TypeScript, as my goal is to create a library that seamlessly integrates with JavaScript without necessitating the use of the 'new' keyword by the user.

P.S.
I am aware that I could create a javascript file along with a '.d.ts' file but that method does not align with my current objectives.

Answer №1

When it comes to TypeScript, the challenge lies in reconciling the different purposes of A(), which leads to a lack of clarity on what you intend it to be.

This approach works:

function A(id): void {
    if (window === this) {
        return new A(id);//<-Error in typescript
    }

    this.e = document.getElementById(id);
    return this;
};

let result = A("test");
result = new A("test").doSomething();

The addition of the version return block adds confusion for the compiler as A now serves two distinct roles.

To silence the complaint and disregard TypeScript's concerns, you could try this:

function A(id): void {
    var about = {
        Version: "0.0.0.1",
    };

    if (id) {
        if (window === this) {
            return new A(id);//<-Error in typescript
        }

        this.e = document.getElementById(id);
        return this;
    } else {
        return <any>about;
    }
};

let result = A("test");
result = new A("test").doSomething();

However, I advise against it. What you're attempting goes against TypeScript's protective mechanisms. Making the typings seamlessly work in this scenario seems challenging.


Edit: In response to your comment, consider something along these lines instead:

class A {
    public static about = {
        Version: "0.0.0.1"
    };

    private e: HTMLElement;

    constructor(id) {
        this.e = document.getElementById(id);
    }

    public doSomething() {
        //Some logic
        return this;
    }
}

let result = new A("test");
result.doSomething();

let about = A.about;

Answer №2

After receiving valuable assistance from MrHen, I have finalized the code as follows:

class A {
    public element;
    public test;
    public doSomething;

    constructor(id) {
        if (id) {
            if (window === this as any) {
                return new A(id);//<-Error in typescript
            }

            this.element = document.getElementById(id);
            this.test = function () {
                console.log("testing"); return this;
            };
            this.doSomething = function () {
                console.log("doing something"); return this;
            };

            return this;
        }
    }
}

let result = ((A as any)("test") as A).doSomething();
result = new A("test").doSomething();

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

Can a JavaScript object be created in TypeScript?

Looking for a way to utilize an existing JavaScript "class" within an Angular2 component written in TypeScript? The class is currently defined as follows: function Person(name, age) { this.name = name; this.age = age; } Despite the fact that Java ...

Dynamically insert JavaScript and CSS files into the header by using the append method

Due to a specific reason, I am loading CSS and scripts into my head tag using the "append" method. For example: $("head").append('<script type="application/javascript" src="core/js/main.js"></script>'); I'm asynchronously pulli ...

Steps for building a Bootstrap grid of thumbnails

I need to display an unknown number of thumbs. Below is a sample of the HTML rendered: <div class="row-fluid"> <ul class="thumbnails"> <li class="span3"> <a href="#" class="thumbnail"> &l ...

Using Jquery and AJAX to dynamically fill out an HTML form based on dropdown selection

My goal is to populate a form on my webpage with information pulled from a MySQL database using the ID of the drop-down option as the criteria in the SQL statement. The approach I have considered involves storing this information in $_SESSION['formBoo ...

Navigating to the default landing page using basic authentication middleware in Express

I'm currently working on implementing basic authorization for an entire website using Express. The goal is to have users enter their credentials, and if correct, they will be directed to the standard landing page. If the credentials are incorrect, the ...

The function createReadStream completes execution without resolving

Currently, I am in the process of developing a program that is aimed at iterating through files within a specified directory in a Linux environment. I have implemented a custom function called "myReadFile" which returns a new promise, and it is expected ...

Submit a single data value to two separate models in JSON format using MongoDB

I recently developed a code with 2 essential functions: module.exports.registerAccount = (reqBody) => { let newAccount = new User({ firstName : reqBody.firstName, lastName : reqBody.lastName, email : reqBody.email, mobileNum : reqBody.m ...

Encountering a 404 error while sending a session ID in a Post request using AngularJS

My services are hosted on a remote server, and I am consuming these services in a local AngularJS app. Everything works fine with REST requests that do not require a SessionID in the header. However, when I add the Session ID in the header, it does not wor ...

Introduction to React with Typescript: Greeting the World

I am attempting to create a Hello World React application with Typescript. Below is the code I have written. Method 1 works without any issues, but method 2 throws an error. Method 1 - TypeScriptComponent.tsx import React from 'react' import Re ...

"Object.entries seems to be returning only the initial object in the list

This is my object var obj = { "first_obj": { "a":1, "status": 1 }, "second_obj": { "a":2, "status": 3 } } I'm struggling to loop through this object using foreach and Object.entries, as the latter only returns the first object. How ...

Adjust the color of the paper in Material-UI

I'm in the process of creating a React project using the material-ui library. Currently, I am facing an issue with customizing the drawer component's background color. After some research, I learned that modifying the paper attribute of the drawe ...

What is the best way to change the size of a QR code

My current HTML code: <input id="text" type="text"/> <div id="qrcode"></div> Previous version of JAVASCRIPT code: var qrcode = new QRCode("qrcode"); $("#text").on("keyup", function () { qrcode.makeCode($(this).val()); }).keyup().focus ...

AngularJS using the ng-controller directive

I am presenting the following HTML code excerpt... <!DOCTYPE html> <html lang="en-US" ng-app> <head> <title>priklad00007</title> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angula ...

Generate incorrect JSON for a negative test in TypeScript

Struggling with navigating TS (amazing) static typing to generate invalid data for a negative test scenario. I am currently working on resolving an issue where the client may pass invalid JSON (double quotes within the value). I believe I have fixed the i ...

Ways to execute the pdf.js node demonstrations?

I've been attempting to run the pdf.js node examples, specifically getinfo.js. Unfortunately, I encountered an issue that resulted in the following error: C:\Repositories\pdf.js>node getinfo.js node:internal/modules/cjs/loader:1080 thro ...

Am I utilizing the htmlspecialchars function properly?

My main objective is to protect the user from malicious code and prevent XSS attacks. I have implemented a series of checks to filter the user's input before storing it in the database. The user input is stored in the $post variable. $post = htmlspec ...

Tips for eliminating one or multiple spaces preceding text in an input field

I implemented input field validation to detect empty fields, but then I discovered that someone could enter white space and still submit the form. Can anyone assist me in removing white space before text while still allowing space in the middle of the text ...

Received an error while attempting to install react-router-dom

I keep encountering this error message whenever I try to install react-router-dom using NPM in VS Code: https://i.sstatic.net/hFshb.png npm ERR! Unexpected end of JSON input while parsing near '...stack-launcher":"^1.0' npm ERR! You can find ...

Managing iframe scrolling using the parent window's scrollbar

I am currently working on an iframe to be utilized across various domains. The functionality of this iframe involves displaying a data list that updates when the bottom of the scroll is reached. An issue I encountered is that the parent window, where the ...

How can HtmlUnit be used to identify and address website pages that display errors?

I've encountered an issue while trying to access this Ajax page through my Java program using the HtmlUnit 2.15 API. It seems that the problem arises from a broken link to a missing file located here. This is the snippet of code I'm working with ...