8

Is there a way to add a isNullOrEmpty(str:string) to the static string object.

such that I can call it:

String.isNullOrEmpty(myobj);

I have found a way to put it on the implementation but that does not help for a method such as this.

3
  • Is there a reason you simply cannot use ! operator? For instance: if(!str) { ... }? Commented Jul 24, 2013 at 19:33
  • mostly I'm just using this as an example Commented Jul 24, 2013 at 19:36
  • Example for what? I mean are you interested specifically in how to check for empty strings or do you want a general answer on how to extend existing objects like string? Commented Jul 24, 2013 at 19:37

3 Answers 3

16

String is defined in lib.d.ts with the following interface

interface StringConstructor {
  ...
}

declare var String: StringConstructor;

so while you can't add methods to a variable, you can add them to the interface, using

interface StringConstructor {
   isNullOrEmpty(str:string):boolean;
}

and them implement them on the variable, using

String.isNullOrEmpty = (str:string) => !str;
Sign up to request clarification or add additional context in comments.

2 Comments

Is this also possible with type Array<T> via the ArrayConstructor?
This should work, but note that there are two interfaces, the generic Array<T>, and the non-generic ArrayConstructor.
5

TypeScript does something called declaration merging, which is explained in section 10.5 of the spec.

The gist of it is you can put members in module foo, and then later on put more members in module foo. As of 0.9 this extends to putting members in the namespace of a class as well, as long as the class is declared first. That's a new feature and I've discovered bugs around it, but it's supposed to work.

So to answer your question specifically you can just do this:

module String {
    export function isNullOrEmpty(s: string): boolean {
        return !s;
    }
}

var s: string;
alert(String.isNullOrEmpty(s).toString());    // true
s = "";
alert(String.isNullOrEmpty(s).toString());    // true
s = "asdf";
alert(String.isNullOrEmpty(s).toString());    // false

Try it out.


Apparently my answer is not complete because String is declared as a var and not a module. Declaration merging doesn't carry over to vars (as of 0.9) which is annoying. There is still a way around this though it's a bit of a hack:

// filea.ts
module String {
    export function isNullOrEmpty(s: string): boolean {
        return !!s;
    }
}
module mynamespace {
    export declare var String: {
        new (value?: any): String;
        (value?: any): string;
        prototype: String;
        fromCharCode(...codes: number[]): string;
        isNullOrEmpty(s: string): boolean;
    }
}

// fileb.ts
/// <reference path="filea.ts" />
module mynamespace {
    var s: string;
    String.isNullOrEmpty(s);    // true
    s = "";
    String.isNullOrEmpty(s);    // true
    s = "asdf";
    String.isNullOrEmpty(s);    // false
}

What's going on in filea is you're putting a function on the var String, and then declaring that mynamespace.String exists with everything String in lib.d.ts has plus what you added. Then, so long as you're working in mysnamespace, references to String will assume you're talking about mynamespace.String. That doesn't really exist so you'll get good ol' String which is what you want.

Like I said it's a bit dirty, but assuming you're following decent namespace conventions you should have a top level namespace where you only have to do this once. If you want to share the String extensions as part of a library though... well you're stuck.

2 Comments

It works on the playground as expected, however breaking it out into two ts files and referencing the string.d.ts one does not allow you to use it as expected
Ah you're right. The issue there is in lib.d.ts String is declared as a var (which apparently doesn't qualify for merging) instead of a module. I don't think you can redeclare a var in the same namespace, but you can declare in a different namespace. I'll amend my answer to explain it.
0

My solution use different approach, because string base type in this phase cannot be extended.

module Type {
    "use strict";

    export module BaseType {
        export class ApplicationString {

            /**
             * Indicates whether the specified string is null or an Empty string.
             *
             * @property string inputString
             * @see https://msdn.microsoft.com/en-us/library/system.string.isnullorempty(v=vs.110).aspx
             */
            static isNullOrEmpty(inputString: string): boolean {
                if (inputString === null || inputString.length === 0) {
                    return true;
                } else {
                    return false;
                }
            }
        }
    }
}

alert(Type.BaseType.ApplicationString.isNullOrEmpty(null));
alert(Type.BaseType.ApplicationString.isNullOrEmpty(""));
alert(Type.BaseType.ApplicationString.isNullOrEmpty("text"));

Demo: TypeScriptPlayground

Comments

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.