Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: Tagged Template Literals shows Error

I am trying to use tagged template literal of ES5 with typescript but it seems like type script does not have full support for it. I have following piece of code.

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 toString method, typescript is showing me following error.

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

I don't know why it's showing me this error. As per the mozilla's doc "The first argument of a tag function contains an array of string values." So it should accept the array of string. But the actual expectation is TemplateStringsArray. not sure how and when the interface TemplateSringsArray is being defined. Currently I am using TemplateSringsArray type to avoid this error. Can anyone please explain whats happening. Thanks. Here's the playground.

like image 618
Hitesh Kumar Avatar asked Feb 28 '17 06:02

Hitesh Kumar


People also ask

What is a tagged template literal?

What are “tagged template literals”? Tagged template literals were enabled by a new technology introduced in ES6, called “template literals”. This is simply a syntax that makes string interpolation possible in JavaScript.

What is a template literal in typescript?

Template literal types build on string literal types, and have the ability to expand into many strings via unions. They have the same syntax as template literal strings in JavaScript, but are used in type positions.

What is ${} in JavaScript?

${} is a placeholder that is used in template literals. You can use any valid JavaScript expression such as variable, arithmetic operation, function call, and others inside ${}. The expression used inside ${} is executed at runtime, and its output is passed as a string to template literals.

How do I use literals in HTML template?

Tagged Template Literals You can put a tag on a template to transform the template before it gets turned into a string. The tag is a function which is called with the first argument being an array of the rest of the arguments are the values of the place holders.


2 Answers

I also can not find any documentation about TemplateStringsArray - but if you just ignore the error by changing the parameter to TemplateStringsArray rather than string[] (and fix a bug with the name member) it seems to work OK

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())
like image 175
Michael Anderson Avatar answered Oct 31 '22 17:10

Michael Anderson


After exploring more, I finally found explanations in the change log. Hope it will help someone. It says

ES2015 tagged templates always pass their tag an immutable array-like object that has a property called raw (which is also immutable). TypeScript names this object the TemplateStringsArray.

Conveniently, TemplateStringsArray was assignable to an Array, so it's possible users took advantage of this to use a shorter type for their tag parameters:

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

However, in TypeScript 2.0, the language now supports the readonly modifier and can express that these objects are immutable. As a result, TemplateStringsArray has also been made immutable, and is no longer assignable to string[].

Recommendation:

Use TemplateStringsArray explicitly (or use ReadonlyArray<string>).

like image 38
Hitesh Kumar Avatar answered Oct 31 '22 18:10

Hitesh Kumar