Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 624
BrunoLM Avatar asked Jun 30 '13 16:06

BrunoLM


People also ask

How do you check if something is an instance of a class JS?

The instanceof operator in JavaScript is used to check the type of an object at run time. It returns a boolean value if true then it indicates that the object is an instance of a particular class and if false then it is not.

How do I check my Instanceof typescript?

Use the instanceof operator to check if an object is an instance of a class, e.g. if (myObj instanceof MyClass) {} . The instanceof operator checks if the prototype property of the constructor appears in the prototype chain of the object and returns true if it does.

How do I find the instance of Java?

The instanceof operator in Java is used to check whether an object is an instance of a particular class or not. objectName instanceOf className; Here, if objectName is an instance of className , the operator returns true . Otherwise, it returns false .


2 Answers

You can currently do it much better this way (TypeScript 3.9):

// tslint:disable-next-line: no-any
type Constructor<T> = new (...args: any[]) => T;

export function ofType<TElements, TFilter extends TElements>(array: TElements[], filterType: Constructor<TFilter>): TFilter[] {
    return <TFilter[]>array.filter(e => e instanceof filterType);
}

Example usage:

class ClassA { }
class ClassB { }

const list: ClassA[] = [new ClassA(), new ClassB()];
const filteredList = ofType(list,  ClassB);
like image 147
Stephen Weatherford Avatar answered Sep 18 '22 17:09

Stephen Weatherford


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.

like image 30
BrunoLM Avatar answered Sep 20 '22 17:09

BrunoLM