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?
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.
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.
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 .
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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With