This question is about ts
inline text interpolation (not template interpolation for the HTML files).
I couldn't find relevant information about my question, so I'm not sure if this is even possible, is kindly appreciated if you provide source documentation in the case of what I'm asking can't be done.
Currently I can do the following:
export class SomeClass {
parseString(name: string): string {
const baseString = `
Hello ${name}...
`;
return baseString;
}
}
// later... when `parseString` is called I get the following result:
parseString('John'); // Hello John...
parseString('Mr. Smith'); // Hello Mr. Smith...
What I want to do is something similar to this:
export class SomeClass {
parseString(name: string, baseString: string): string {
return baseString;
}
}
// later... when `parseString` is called I want to get the following result:
parseString('John', `Hello Mr.${name}`); // Hello Mr.John...
parseString('Mr. Smith', `Hi ${name}`); // Hi Mr. Smith...
The syntax I'm proposing is completely wrong because baseString
is evaluated before name
even exists within its scope or has a value, and so it always returns the string without the variable value: Hello Mr.
and Hi
.
I don't care about the syntax, any means for taking advantage of text interpolation from a variable would great. Ultimately I would like to be able to do something like this:
/**
* The reason that I'm using `of` from `RxJS` is that
* I want to show that I want to be able to gather labels from
* anywhere, let's say a REST API or a service (?)
**/
of(`Greetings ${name}...`).subscribe(val => {
const name = 'John';
console.log(val); // Greetings John...
});
Currently, to fulfill all this I just use:
parseString(name: string, baseString: string): string {
return baseString.replace(/\$\{name\}/g, 'John');
}
But I'm wondering if there's a feature I'm missing with text interpolation.
Edit:
The main difference between this question and the suggested duplicate is that the suggested doesn't care if the back quoted text might be dynamic, here I am trying to be able to "create" those back quoted strings from scratch or based on other variables.
Edit 2:
The suggested duplicate does answer my question here, but works only in ES6
environments.
Edit 3:
Explaining briefly, the ES5/ES6
issue. I realized that the suggested duplicate question creates a Function
object in runtime, with syntax only available in ES6
, which means it'll only work on ES6
environments. ES5
is not supported by the other question/answer. On the contrary, Angular TypeScript compilator can create code compatible with ES5
when text interpolation is used.
CodePudding user response:
Try this
/**
* Text interpolation
* https://www.w3schools.com/js/js_string_templates.asp
*
* Example:
* const text: string = this.helloI18nTag; // <-- "Hello ${name}, welcome"
* const res = StringUtil.interpolate(text, { name: 'John Connor' });
* console.log(res); // <-- "Hello John Connor, welcome"
*
* @param template : string to interpolate
* @param args : an object wiht key -> value to replace
* @returns
*/
public static interpolate(template: string, args: { [key: string]: string }): string {
if (typeof args !== 'object') {
return template;
}
try {
return new Function('return `' template.replace(/\$\{(. ?)\}/g, '${this.$1}') '`;').call(args);
} catch (e) {
// ES6 syntax not supported
}
Object.keys(args).forEach((key) => {
template = template.replace(new RegExp('\\$\\{' key '\\}', 'g'), args[key]);
});
return template;
}
interpolate('Hello ${name}', {name: 'John'});
CodePudding user response:
If all you’re ever doing is concatenating baseString
and name
, you could just do the following:
parseString(name: string, baseString: string): string {
return baseString name;
}
Or if it won’t always be that simple, you could pass a function instead of baseString
:
// inside class
parseString(name: string, greeting: (s: string) => string): string {
return greeting(name);
}
function makeGreeting(name: string) {
return `Hi ${name}, I’m Jack.`;
}
console.log(parseString("Bill", makeGreeting)); // “Hi Bill, I’m Jack.”