Employing various Class Methods based on the chosen target compiler option

Is there a way to instruct TypeScript to utilize different implementations of methods within the same class, based on the specified target option in the tsconfig.json file?

I am currently transitioning one of my scripts to TypeScript to streamline management of codebases by consolidating an ES5 and an ES6 file into a single source. Due to TypeScript's ability to switch output targets in the tsconfig.json file, I aim to have a single version that can be easily updated and maintained.

The challenge arises from using a generator in the ES6 version, which should not pose a problem as TypeScript automatically adds a pseudo-generator to the top of the ES5 output. However, my current Pseudo-Generator implementation in the ES5 file is more concise and clean.

Possible Solutions

Is there a method to override the respective "generator" method or use specialized comment annotations (such as //@ts-target) to specify which code (function body) to use based on the selected target in the configuration file, even if it is not documented officially?

Integrating an additional function or script into the TypeScript compiler process may provide assistance since I compile both ES files through a small node.js script without directly altering the tsconfig.json file.

Alternatively, is there an extension available to segregate different methods of a class into separate files? This would enable extraction of the respective "generator" methods. However, this approach raises questions regarding linking them based on the target, given that I utilize /// <reference /> linking in the main script file for consolidation.

Any innovative suggestions?

class Option {
    ///@ts-target ES5
    __walkerVariable1:any undefined
    __walkerVariable2:any undefined
    __walkerVariable3:any undefined
    walker() {
        /* Pseudo-Walker Code for ES5 */
    }

    ///@ts-target ES6
    *walker() {
        /* Real Walker Code for ES6 */
    }
}

Currently, a Pseudo-Generator code is injected into the ES5 version of my script. I aspire to address this challenge by implementing a different method/function that houses my personal Pseudo-Generator. Therefore, I seek guidance on how to instruct TypeScript to disregard the Pseudo-Generator in ES6/Real-Generator in ES5 and only include one of them based on the chosen target option.

Answer №1

After some careful consideration, I managed to tackle a tricky problem by seeking guidance from an informative GitHub issue.

In my approach, I utilize a custom node.js script to compile TypeScript files into two distinct JavaScript versions, ES5 and ES6. This involves leveraging the TypeScript API and utilizing the ts.createProgram method, which allows for the integration of a host object as a third parameter. The host object facilitates various compiler processes, including the file loader method known as getSourceFile.

The remainder of the process is relatively straightforward: I employ regular expressions to identify and filter custom comment annotations such as \\\@ts-target:ES5 and \\\@ts-target:ES6. While it may not be the most elegant solution, it effectively achieves the desired outcome!

function compileTS(){
    let config = readConfig("ts/tsconfig.json");
    let host = ts.createCompilerHost(config.options);
    let sourceFile = host.getSourceFile;

    // Generating ES5 JavaScript
    (function(config){
        host.getSourceFile = function(filename) {
            if(filename === "ts/options.ts"){
                let file = fs.readFileSync("./ts/options.ts").toString();
                file = file.replace(/[ ]+\/\/\/\@ts\-target\:ES6\s+([\s\S]*)\/\/\/\@ts\-target\:ES6/gm, "");
                return ts.createSourceFile(filename, file, ts.ScriptTarget.ES5, true);
            }
            return sourceFile.call(host, filename);
        }
        let program = ts.createProgram(config.fileNames, config.options, host);
        let emitResult = program.emit();
        report(ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics));
        if(emitResult.emitSkipped){
            process.exit(1);
        }
    }(config));

    // Generating ES6 JavaScript
    config.options.target = 2;
    config.options.outFile = "../dist/js/tail.select-es6.js";
    (function(config){
        host.getSourceFile = function(filename) {
            if(filename === "ts/options.ts"){
                let file = fs.readFileSync("./ts/options.ts").toString();
                file = file.replace(/[ ]+\/\/\/\@ts\-target\:ES5\s+([\s\S]*)\/\/\/\@ts\-target\:ES5/gm, "");
                return ts.createSourceFile(filename, file, ts.ScriptTarget.ES2015, true);
            }
            return sourceFile.call(host, filename);
        }
        let program = ts.createProgram(config.fileNames, config.options, host);
        let emitResult = program.emit();
        report(ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics));
        if(emitResult.emitSkipped){
            process.exit(1);
        }
    }(config));
}

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

What is the best way to access the attribute of an AJAX response?

resp.getWriter().write("msg=1?id=" + l1); Within the code snippet below, I am able to retrieve the responseText. However, I am wondering how can I extract an attribute from the response text. Sample AJAX Code: function updatecategories(cu) { var r1 = ...

Does Next js Backend support multithreading as a default feature?

As I begin my project, I am utilizing the built-in Node js server within Next js by running the next start command. However, I am uncertain as to whether it has multithreading capabilities. My inquiry is this: Would you suggest sticking with the built-in ...

When sending a POST request, the req.body.someElement parameter is not defined

Encountering an issue with a post request, as req.body is returning undefined values. Despite researching on Google and Stack Overflow, the provided solutions have not resolved the problem. Although logging the name shows a value, trying to access req.body ...

Exploring the concept of asynchronous subscriptions in Angular

My current issue seems to be related to asynchronous programming, specifically with the subscription not running at the desired time. I typically approach this problem from both the user's and developer's perspectives. User's Perspective: ...

Using iScroll without animation by using scrolltoelement on an iPhone PhoneGap application

I've been working on an iOS PhoneGap app that uses Backbone and some other libraries. To handle scrolling, I implemented iScroll which has been functioning properly. However, I encountered a problem with the following code snippet: events: { &apo ...

Strategies for creating a dynamic progress bar using jQuery and JavaScript

I'm currently working on a project that involves increasing a percentage number while filling up the background color inside it based on the percentage value. The current setup is functional in terms of animating the background, but I need it to dynam ...

Different options for determining network connectivity on a website

Seeking Network and Location Information on ASP.Net Core MVC Web Application After some investigation, I came across the Navigator API online. For acquiring location data, it functions flawlessly. navigator.geolocation.getCurrentPosition(function (posi ...

Exploring the intricacies of React Router parameters

I have been facing some issues with my routing setup. Specifically, I have a static route called list and a dynamic route called user/:id. The problem arises when navigating between these two pages. (1) Whenever I navigate to the list route from the user/: ...

Heroku Node.js - Cross-Origin Resource Sharing (CORS) is functioning correctly for all API requests except for when using the image upload

Our web application contains numerous APIs that retrieve data from a Node.js server deployed on Heroku. Most of the APIs function correctly, with the exception of one that allows users to upload images to the server. While this API worked flawlessly in o ...

What is the best method to evaluate lambda functions in a functional React Component using Jest and Enzyme?

My current challenge involves creating a pulldown tab in a TDD style. I have been struggling to test if the function inside the component triggers on the button's click event. The jest logs keep showing me errors indicating that the object I'm tr ...

Tips for handling notifications that have been read and unread in a React application

In my current project using React JS, I am tasked with creating a notifications component that will display account-related activities. The notifications need to be sorted into read and unread categories. My main question is how should I manage the read a ...

The useAutocomplete function in Material-UI fails to consider the disabled

Currently, I am working on developing my own Autocomplete component by utilizing the useAutocomplete hook from the mui/base package. Most parts of the implementation are functioning correctly, except for the disabled option. My expectation is that the com ...

Tips for programmatically choosing images from a Google Photos collection?

Currently, I am attempting to use code in the console to automatically choose a photo from a Google Photos Album while browsing. I've tried this method so far: const photo = document.getElementsByClassName('p137Zd')[0].parentElement photo. ...

Extract data from the HTML source code in JavaScript and transfer it to a personalized JavaScript variable within Google Tag Manager

Running an e-commerce website on Prestashop and facing an issue with data layer set up. Instead of a standard data layer, the platform generates a javascript variable called MBG for Enhanced E-Commerce implementation. <script type="text/javascript"> ...

It appears that the flex-grow property is not functioning as expected

I am working with a parent div and two children divs underneath it. I noticed that when I set the flex-grow property of the first child to zero, its width remains constant. However, if I add text to the second child, the width of the first child decreases. ...

Synchronize CSS Properties with JavaScript Event

Is there a more efficient way to synchronize two properties using JavaScript or JQuery? For instance, when I have an editable text field and I switch it to an input box upon double click, how can I ensure that the input box adjusts its size along with the ...

Tracking the email field in a React form with refs

Hey there! I'm a music engineer working on my own personal website using React. I'm currently facing an issue with creating a contact form that allows users to input a subject in a text field, a message in a textarea, and then click a "reach out" ...

Is there a way to transfer a JSON map object from Flask and then utilize it as a JavaScript object?

python server code from flask import Flask, render_template, request import os import sys import json data_raw = [('0', '1', '0', '0'), ('0', '0', '1', '0'), ('1', ...

Is it recommended to start off by creating a new Discord collection for the client's commands when setting up an advanced commands handler with discord.js?

Currently, I am delving into the realm of advanced command handling by moving beyond basic commands. As I follow various YouTube tutorials and guides to aid me in this endeavor, I have encountered a roadblock. An error stating that "Discord.Collections is ...

Obtain the currently selected HTML element using tinyMCE

Within my editor, I have the ability to choose text and show it using the code below: alert(tinyMCE.activeEditor.selection.getContent({format : "html"})); The problem is that this function only returns text and not HtmlElement. This means I am unable to ...