FAISAL
FAISAL

Reputation: 34693

Typescript Extend String interface Runtime Error

I am extending the typescript String interface in my Angular app. I have added a method translate() which is accessible throughout my app. I do not get any compile errors.

However, I get a runtime error:

"TypeError: "Translate this string".translate is not a function"

Any ideas what I might be doing wrong?


Here are the screenshots of my implementation:

Declaration:

enter image description here

Implementation

enter image description here

Calling:

enter image description here

Upvotes: 1

Views: 2512

Answers (3)

FAISAL
FAISAL

Reputation: 34693

I was able to fix this problem. Here is an update on how to solve this issue:


1. Create a file global.d.ts and add the interface extension definitions there.

export { };
declare global
{
    interface String
    {
        /**
         * Translates the given string according to the culture provided.
         * @param cultureName The culture name of the translation target.
         * @returns The translated string.
         */
        translate(cultureName: string): string;
    }
}

2. Create another file with the interface extension methods definition. In my case I named it string.extensions.ts

/**
 * Translates the given string according to the culture provided.
 * @param cultureName The culture name of the translation target.
 * @returns The translated string.
 */    
String.prototype.translate = function(cultureName: string): string
{
    const inputValue = this;

    // Do the translation here
    const translatedValue = 'Willkommen bei meiner App'; // Only for example

    return translatedValue ;
};

3. In your app boot file, in my case its main.ts, add a reference to the global.d.ts and the file containing your extension methods definitions.

/// <reference path="app/core/extensions/global.d.ts" />
//...
import './app/core/extensions/string.extensions';

You just need to import this file once in your project (main.ts) and then you can use it anywhere in the code.

4. Example use in my AppComponent

import {Component} from '@angular/core';    

@Component({
    selector: 'my-app',
    template: `
        Original Value: <h3>{{ originalValue }}</h3>
        Translated Value: <h3>{{ translatedValue }}</h3> 
    `
})
export class AppComponent {

    private originalValue:string;
    private translatedValue:string;

    constructor() {          
        this.originalValue = 'Welcome to my App';
        this.translatedValue = 'Welcome to my App'.translate('de-DE'); 
    }      
}

That's all you need to do to solve this annoying problem.

Here is a link to working plunker: Plunker Demo

Upvotes: 9

Victor Shelepen
Victor Shelepen

Reputation: 2256

I guess that your declaration is in a separated files. It still uses the base declaration. It is not reachable to the code. Try use the direct import from the file or this one.

///<reference path="test.d.ts"/>

Upvotes: 1

Kokodoko
Kokodoko

Reputation: 28148

This works for me:

Declare an interface

interface String {
    translate():string
}

Usage

String.prototype.translate = function(){
     return "boink"
}

let str : string = "test";
let a : string = str.translate();
console.log(a);   // logs "boink"

Upvotes: 1

Related Questions