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.
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.
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.
${} 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.
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.
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())
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>
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With