String.Format not work in TypeScript

Антон Степанов picture Антон Степанов · Nov 19, 2013 · Viewed 131.5k times · Source

String.Format does not work in TypeScript.
Error:

The property 'format' does not exist on value of type 
 '{ prototype: String; fromCharCode(...codes: number[]): string; 
 (value?: any): string; new(value?: any): String; }'.

attributes["Title"] = String.format(
    Settings.labelKeyValuePhraseCollection["[WAIT DAYS]"],
    originalAttributes.Days
);

Answer

Fenton picture Fenton · Nov 19, 2013

String Interpolation

Note: As of TypeScript 1.4, string interpolation is available in TypeScript:

var a = "Hello";
var b = "World";

var text = `${a} ${b}`

This will compile to:

var a = "Hello";
var b = "World";
var text = a + " " + b;

String Format

The JavaScript String object doesn't have a format function. TypeScript doesn't add to the native objects, so it also doesn't have a String.format function.

For TypeScript, you need to extend the String interface and then you need to supply an implementation:

interface String {
    format(...replacements: string[]): string;
}

if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number]
        : match
      ;
    });
  };
}

You can then use the feature:

var myStr = 'This is an {0} for {0} purposes: {1}';

alert(myStr.format('example', 'end'));

You could also consider string interpolation (a feature of Template Strings), which is an ECMAScript 6 feature - although to use it for the String.format use case, you would still need to wrap it in a function in order to supply a raw string containing the format and then positional arguments. It is more typically used inline with the variables that are being interpolated, so you'd need to map using arguments to make it work for this use case.

For example, format strings are normally defined to be used later... which doesn't work:

// Works
var myFormatString = 'This is an {0} for {0} purposes: {1}';

// Compiler warnings (a and b not yet defines)
var myTemplateString = `This is an ${a} for ${a} purposes: ${b}`;

So to use string interpolation, rather than a format string, you would need to use:

function myTemplate(a: string, b: string) {
    var myTemplateString = `This is an ${a} for ${a} purposes: ${b}`;
}

alert(myTemplate('example', 'end'));

The other common use case for format strings is that they are used as a resource that is shared. I haven't yet discovered a way to load a template string from a data source without using eval.