Search code examples
genericstypescript

How can I check if element is an instanceof U?


I want to add elements of type any to an array and later get the elements from this array that are numbers:

function OfType<T, U>(list: T[]) : U[]
{
    var result: U[] = [];

    list.forEach(e => {
        // I want to check if e is of type U
        //if (typeof(e) === typeof(U)) // ERROR: doesn't work
            result.push(<U><any>e);
    });

    return <any[]>result;
}


var list: any[] = [];
list.push("A");
list.push(2);

var result = OfType<any, number>(list);

alert(result.toString());

But it doesn't allow me to check the type of the elements against a generic type.

Is there a way to accomplish this?


Solution

  • As Judah pointed out it is unlikely to be possible using generic types alone. I found a workaround where I send in one more parameter with the type...

    function OfType<T, U>(list: T[], arg: Function) : U[]
    {
        var result: U[] = [];
    
        list.forEach(e => {
            // extract the name of the class
            // used to match primitive types
            var typeName = /function\s*([^(]*)/i.exec(arg+"")[1].toLocaleLowerCase();
    
            var isOfType = typeof(e) === typeName;
    
            // if it is not primitive or didn't match the type
            // try to check if it is an instanceof
            if (!isOfType)
            {
                try {
                    isOfType = (e instanceof arg)
                }
                catch (ex) { }
            }
    
            if (isOfType)
                result.push(<U><any>e);
        });
    
        return <any[]>result;
    }
    

    Usage:

    var numbers = OfType<any, number>(list, Number);
    var foos = OfType<any, Foo>(list, Foo);
    
    alert("Numbers: " + numbers);
    alert("Foos: " + foos);
    

    Little redundancy, if someone know a way to remove this redundancy please leave a comment or edit this code.

    Or, for primitive types only I could use filter as Judah mentioned.