Encountering an Error with Tagged Template Literals in TypeScript

I'm attempting to utilize tagged template literals from ES5 with TypeScript, but it appears that TypeScript doesn't fully support it. Here is the code snippet I have:

class TemplateLiterals { 
    age: number = 24;
    name: 'Luke Skywalker'
    private tag(strings: string[], personExp, ageExp) :string{
        var str0 = strings[0]; // "that "
        var str1 = strings[1]; // " is a "
        var ageStr;
        if (ageExp > 99) {
            ageStr = 'centenarian';
        } else {
            ageStr = 'youngster';
        }
        return str0 + personExp + str1 + ageStr;
    }
    toString() {
        return this.tag `that ${ this.name } is a ${ this.age }`;
    }
}

In the toString method, TypeScript displays the following error:

Argument of type 'TemplateStringsArray' is not assignable to parameter of type 'string[]'.
Property 'push' is missing in type 'TemplateStringsArray'.

I am puzzled by why this error occurs. According to Mozilla's documentation, "The first argument of a tag function contains an array of string values." Therefore, it should accept the array of strings. However, there is an expectation of TemplateStringsArray. I am currently using the TemplateStingArray type to bypass this error. Can someone explain what's happening? Thanks. You can view the code on the playground.

Answer №1

After further exploration, I finally uncovered clarifications in the revision history. Hopefully, this information will benefit someone. According to the documentation:

ES2015 tagged templates always pass their tag an immutable array-like object that contains a property named raw (which is also immutable). This object is referred to as TemplateStringsArray by TypeScript.

Previously, TemplateStringsArray could be assigned to an Array, allowing users to use a more concise type for their tag parameters:

function myTemplateTag(strs: string[]) {
    // ... 
} 

However, with the introduction of TypeScript 2.0, the readonly modifier is now supported in the language and can indicate immutability of objects. As a result, TemplateStringsArray has been made immutable and is no longer compatible with string[].

Recommendation:

Explicitly use TemplateStringsArray (or utilize ReadonlyArray<string>).

Answer №2

Documentation on TemplateStringsArray appears to be scarce, but a workaround for the error involves changing the parameter to TemplateStringsArray instead of string[], and addressing a bug related to the name member - this seems to resolve the issue

class TemplateLiterals { 
    age: number = 24;
    name: string = 'Luke Skywalker'
    private tag(strings: TemplateStringsArray, personExp, ageExp) :string{
        var str0 = strings[0]; // "that "
        var str1 = strings[1]; // " is a "
        var ageStr;
        if (ageExp > 99) {
            ageStr = 'centenarian';
        } else {
            ageStr = 'youngster';
        }
        return str0 + personExp + str1 + ageStr;
    }
    toString() {
        return this.tag `that ${ this.name } is a ${ this.age }`;
    }
}

var luke: TemplateLiterals = new TemplateLiterals()
console.log(luke.toString())

Answer №3

The previous solution did not solve my problem, possibly due to a change in requirements as of the current month (December 2021).

However, I managed to fix the issue by utilizing ReadonlyArray<string> instead of string[].

Feel free to use the following sample function if it can assist anyone else.

function myCustomTag(strs: ReadonlyArray<string>) {
  // Perform necessary actions here.
} 

Answer №4

Dealing with Angular's $localize function, I encountered a similar issue. The mistake I made was using it incorrectly:

// Incorrect usage:
const translated = $localize(`Something to translate!`);
// Correct way is without parentheses:
const translated = $localize`Something to translate!`;

Hopefully, this tip will help someone save some time :)

Answer №5

Exploring the process of simple template evaluation in TypeScript:

// Function for evaluating template tags:
function _E(t: TemplateStringsArray, ...args: Array<any>): string {
    return t.reduce((a, c, i) => a + c + (args[i] ?? ''), '');
}

Testing it out:

const first = 'one';
const second = null; // to be ignored
const third = 123;

console.log(_E`${first}-${second}-${third}`);
//=> one--123

It's important to note that in our tag function, we intentionally convert any null or undefined values into empty strings, but you have the flexibility to handle them as needed.

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

The sorting of elements using the jQuery sort() function encounters issues on webkit browsers

Looking for a solution to sort elements by a number? Consider this part of a function that does just that. The number used for sorting is fetched from a data-ranking attribute of the element: $(".tab_entry").sort(function(a,b){ return parseFloat(a.dat ...

User class instantiation in livequery is initiated

Is it possible to initialize the user class in a live query? I have initialized the user class in my index.js and it shows up in my network inspector. However, when I attempt to query, nothing appears in the websocket. Below is the code showing how I init ...

Geocode promise left unattended

After reviewing my code, I discovered that it is executing too quickly for use in the Angular template. Here is an excerpt of the problematic code: this.dataService.getSomeData().subscribe(async (res) => { this.historyList = res; this.historyList.fo ...

Unable to add text to texarea using jquery

I recently discovered and am experimenting with smiley and uikit to create a feature that allows users to insert emoticons into a textarea. Here is the HTML structure: <textarea class="smiley-input uk-width-1-1"></textarea> <button type= ...

Using GSAP in an Ionic application

What is the best way to add the GSAP library to an Ionic project? Simply running npm install gsap doesn't seem to work when I try to import it using: import { TweenMax, TimelineMax} from "gsap"; I am currently using TypeScript. Thank you. ...

ng-repeat not functioning properly with data defined in XMLHttpRequest

I have a problem with my HTML and AngularJS code. Initially, I defined the list in my controller which worked fine: <li ng-repeat="a in idmasVesselstableList"><a>{{a.table_name}}</a></li> And here is how I set up the controller: ...

Refresh the pagination in a jQuery DataTable

I have incorporated DataTable for pagination within my table. The data in the table is loaded through ajax requests, and I am utilizing my custom functions to populate the table manually by interacting with its DOM elements. However, I am facing an issue ...

Leveraging JSON Data for Avatars in React.js

Struggling to arrange 10 Avatars side by side for showcasing the user list. However, encountering an issue where the Avatars are being duplicated and showing incorrect initials when passing JSON data. Experimented with this in Code Sandbox linked below. h ...

How can AngularJS utilize variables from an external JavaScript <script> file within an HTML document?

As someone unfamiliar with AngularJS, I have a simple inquiry regarding the subject. The code on my page begins by defining an app and controller: <script> var isisApp = angular.module('isisApp', []); isisApp.controller('Acco ...

Timepicker.js - Incorrect Placement of Time Picker in Certain Scenarios

Utilizing the timepicker.js library to select a time, I am encountering an issue. When clicking on the input field, the timepicker should appear next to it. This function works as expected when the input is within the main view of the document. However, if ...

Using useState in ReactJS does not allow setting state data

I am working with a react component that handles agreements. import React from "react"; import { AgreementInfo } from "../../../../models/shop"; import { MdClose } from "react-icons/md"; import moment from "moment"; ...

Exploring the Difference Between Passing 0 and an Empty Array as the Second Argument in useEffect with React Hooks

Recently, I came across someone using 0 instead of an empty array for the second argument in useEffect. Instead of the typical: useEffect(() => { console.log('Run once'); }, []); they had: useEffect(() => { console.log('Run o ...

The argument provided needs to be a function, but instead, an object instance was received, not the original argument as expected

I originally had the following code: const util = require('util'); const exec = util.promisify(require('child_process').exec); But then I tried to refactor it like this: import * as exec from 'child_process'; const execPromis ...

Ways to retrieve all elements based on their class names?

What is the equivalent of using $('.class') in JQuery to get all elements by class name with pure JavaScript? ...

Unable to render the JSON data that was retrieved from a jQuery AJAX request

I am having trouble displaying JSON data that is returned from an AJAX call. Can someone please assist me? I am new to this. $.ajaxSetup({ cache: false, timeout: 5000 }); //String.prototype.toJSON; var the_object = {}; function concatObject(obj) { ...

Can someone explain why I am consistently receiving the value of undefined when accessing the file Object?

Hi there, I'm new to this so I could really use some assistance... I'm currently working on an API where only registered users can upload a card with an image of their asset for rent. In my cards.js file, I have a post request that should respo ...

Progress Bar Countdown Timer

I have made some progress on my project so far: http://jsfiddle.net/BgEtE/ My goal is to achieve a design similar to this: I am in need of a progress bar like the one displayed on that site, as well as the ability to show the days remaining. Additionally ...

fill out an HTML form and send it in

When submitting a form with two components, only the first form 'School' and the submit button itself are successfully submitted. The second form 'pool' seems to disappear somehow. <form method='get'> <select nam ...

Issue with running JavaScript functions on HTML elements in a partial when updating it with AJAX in ASP.NET MVC Core

My asp.net mvc core 2.2 application includes a page where a partial is loaded: <div class="col-md-9" id="content"> @await Html.PartialAsync("_TrainingContent") </div> The partial contains a model and loads a video using the video.js playe ...

What is the best way to access a reference to the xgrid component in @material-ui?

Is there a way to obtain a global reference to the xgrid component in order to interact with it from other parts of the page? The current code snippet only returns a reference tied to the html div tag it is used in, and does not allow access to the compo ...