1

This is mainly a question on how to add/extend any existing type with static custom methods.

I want to have the String prototype extended with a function, e.g. isNullOrEmpty which should be invoked the C# way:

if(!String.isNullOrEmpty(myStringToCheck)){
    // do things as of myStringToCheck is set to something
}

In plain javascript I could do something like

String.isNullOrEmpty = function (s) {
    if (s == null || s === "")
        return true;

    return false;
}

But, when calling it inside a TypeScript it tells me

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

How can this be done so it is known by TypeScript?

Edit #1

How is String.fromCharCode() implemented which is already known by TypeScript?

Edit #2

Because of other dependencies in the project I'm currently only allowed to use TypeScript 1.0!

Edit #3

String.d.ts

interface StringConstructor {
    isNullOrEmpty(): boolean;
}

interface String {
    format(...args: any[]): string;
    isNullOrEmpty(): boolean;
} 

and my String.ts

/// <reference path="../../../typings/String.d.ts"/>

String.prototype.format = function (): string {
    var formatted = this;
    for (var i = 0; i < arguments.length; i++) {
        var regexp = new RegExp("\\{" + i + "\\}", "gi");
        formatted = formatted.replace(regexp, arguments[i]);
    }
    return formatted;
}

String.isNullOrEmpty = function(s) { <-- here is the exception
    if (s == null || s === "")
        return true;
    return false;
}

Solution #1 (TypeScript version > 1.0?)

see first answer by MartyIX

Solution #2 (workaround for TypeScript version 1.0)

see second answer

KingKerosin
  • 3,639
  • 4
  • 38
  • 77

2 Answers2

2
// String.ts
interface StringConstructor {
    isNullOrEmpty(text: string): boolean;
}

interface String {
    isNullOrEmpty(text: string): boolean;
}

String.isNullOrEmpty = (s:string):boolean => {
    return (s == null || s === "");
};

// OtherFile.ts
///<reference path="path/to/String.ts" />

if(!String.isNullOrEmpty("test")){
    // Do something
}

var isEmpty = String.fromCharCode(100).isNullOrEmpty("Nah");

This works for me. The interface extends StringConstructor.

MartyIX
  • 27,828
  • 29
  • 136
  • 207
  • And how would I implement the method? I have a `String.ts` where I have some more extensions already implemented (but currently only new functions instead of `static` functions). – KingKerosin Oct 14 '15 at 08:09
  • Please see the edited answer. You don't need to do anything fancy here. Just do what you would do in plain JavaScript. – MartyIX Oct 14 '15 at 08:14
  • This is not working. Is still says `The property 'isNullOrEmpty' does not exist on value of type '{ prototype: String; fromCharCode(...codes: number[]): string; (value?: any): string; new(value?: any): String; }'.` Maybe an version-issue? – KingKerosin Oct 14 '15 at 08:16
  • What about the latest version? – MartyIX Oct 14 '15 at 08:25
  • See `Edit #3` - still not working with the same error-message. `StringConstructor` is also not known in `TypeScript 1.0` so I guess this is an issue – KingKerosin Oct 14 '15 at 08:34
  • I don't see any reference to `String.d.ts` in `String.ts` in your code. For start, it may be a good idea to put it all in one file. – MartyIX Oct 14 '15 at 08:37
  • It was there. But not working. Even if all is packed into one file it is still not working – KingKerosin Oct 14 '15 at 08:39
  • 1
    Well, if you my code to http://www.typescriptlang.org/Playground, it works. Unfortunately, I don't have TypeScript 1.0, it's rather old. – MartyIX Oct 14 '15 at 08:42
  • Your example may work, but there are complier errors: [see playground](http://www.typescriptlang.org/play/#src=%0D%0Ainterface%20StringConstructor%0D%0A%7B%0D%0A%09isNullOrEmpty(text%3A%20string)%3A%20boolean%3B%0D%0A%7D%0D%0A%0D%0Aexport%20interface%20String%0D%0A%7B%0D%0A%0D%0A%09isNullOrEmpty(test%3A%20string)%3A%20boolean%0D%0A%7D%0D%0A%0D%0A%0D%0A%0D%0AString.isNullOrEmpty%20%3D%20(test%3A%20string)%3A%20boolean%20%3D%3E%0D%0A%7B%0D%0A%09return%20(!test%20%7C%7C%20!test.length)%3B%0D%0A%7D%0D%0A) – prespic Dec 27 '16 at 14:29
  • @prespic: The compiler error is gone when you remove "export" keyword. I don't work with latest version of TypeScript so I can't help further. – MartyIX Dec 27 '16 at 15:01
  • Yes, my fault. It is working now. Here is [fixed playground](http://www.typescriptlang.org/play/index.html#src=interface%20StringConstructor%0D%0A%7B%0D%0A%09isNullOrEmpty(text%3A%20string)%3A%20boolean%3B%0D%0A%7D%0D%0A%0D%0Ainterface%20String%0D%0A%7B%0D%0A%09isNullOrEmpty(test%3A%20string)%3A%20boolean%0D%0A%7D%0D%0A%0D%0AString.isNullOrEmpty%20%3D%20(test%3A%20string)%3A%20boolean%20%3D%3E%0D%0A%7B%0D%0A%09return%20(!test%20%7C%7C%20!test.length)%3B%0D%0A%7D). – prespic Dec 27 '16 at 15:19
1

As by comments from @MartyIX, it seems to be a problem with TypeScript 1.0. As a workaround I've added a method to the prototype of String:

String.d.ts (definition)

interface String {
    isNullOrEmpty(text: string): boolean;
} 

String.ts (implementation)

String.prototype.isNullOrEmpty = function(text) => {
    if (text == null || text === "")
        return true;

    return false;
}

which can be used

if(!String.prototype.isNullOrEmpty(myStringToCheck)){
    // do things as of myStringToCheck is set to something
}
KingKerosin
  • 3,639
  • 4
  • 38
  • 77