1

I'm trying to create a TypeScript definition file for this String.format for JavaScript implementation, but I'm struggling.

I'm still new to TypeScript and I've read many articles/snippets on how to create definitions. One of the best resources I've found is Steve Fenton's blog article Complex TypeScript Definitions Made Easy. I've followed the suggested examples but have so far been unsuccessful.

The problem is because the external Javascript adds a method to "String". I've tried to "declare" the String class as follows:

declare class String {
    declare function format(str: string, obj0: any, obj1?: any, obj2?: any): string;
}

This results in the error: Duplicate identifier 'String'

I've also tried to describe the type information using an interface:

interface String {
    format(str: string, obj0: any, obj1?: any, obj2?: any): string;
}

The interface itself seems ok but if I try to call:

String.format("The {0} brown {1}!", "quick", "fox") 

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

I'm assuming this is because format is a static method (in TypeScript terms anyway), but is defined as an instance method on the interface (since interfaces can't contain static method definitions).

I may be going in totally the wrong direction with this, or may have a totally flawed understanding of some element of Javascript, TypeScript or both. Can anybody at least nudge me in the right direction please?

1

1 Answer 1

0

Currently, I don't think there is a way because String is defined as follows and declare var doesn't merge with other types.

declare var String: {
    new (value?: any): String;
    (value?: any): string;
    prototype: String;
    fromCharCode(...codes: number[]): string;
}

In the latest TypeScript github it is defined with a declare var String: StringConstructor which is extensible. So in the next version you can do:

interface StringConstructor{
    format(str: string, obj0: any, obj1?: any, obj2?: any): string;
}

I understand that this isn't the answer you are hoping for but I think you have to wait for a next version to fix this.

Offcourse you can use it now by casting it to for example any.

edit After the comment from below

This is possible now with the current TypeScript version (1.3)

This will give you some safety, the cast too customstring doesn't look really nice but it gives you some safety during a compile and it will still catch errors when you type format wrong (frmat for example).

interface CustomString {
    format(str: string, obj0: any, obj1?: any, obj2?: any): string;
}
var foo = "foo";
var ret = (<CustomString><any>foo).format("bar", "baz");
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer, I appreciate it. You couldn't just elaborate on your last comment just a little more could you please? What would I cast to "any"?
Added my answer with the info about the cast :)
Thanks! I've added the interface you suggested above to the definition file and changed my typescript code to: (<CustomString><any>String).format("The {0} brown {1}", "quick", "fox"); It's not perfect (like you say) but it's not too ugly. It will certainly do until the next version of TypeScript.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.