8

我想将类型的元素添加any到数组中,然后从该数组中获取数字元素:

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());

但它不允许我根据泛型类型检查元素的类型。

有没有办法做到这一点?

4

3 回答 3

9

您目前可以通过这种方式做得更好(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);
}

示例用法:

class ClassA { }
class ClassB { }

const list: ClassA[] = [new ClassA(), new ClassB()];
const filteredList = ofType(list,  ClassB);
于 2020-12-05T01:23:55.640 回答
1

Javascript typeof 适用于对象的实例,而不是类型本身。(毕竟,TypeScript 泛型在编译后的 JavaScript 中消失了。)

您需要获取 U 的一个实例,对其调用 typeof,并将其与 typeof(e) 进行比较。

请记住,JavaScript 中的类型信息不像 .NET 框架中那样丰富。typeof(myCustomObject) 将返回 'object',即使该对象是 Foo 类的实例。

在您的情况下,您正在尝试构建一个 .OfType 方法,该方法将数组过滤为仅数字。你可以这样写:

var list: any[] = [];
list.push("A");
list.push(2);
var numbers = list.filter(e => typeof(e) === "number");
于 2013-06-30T19:20:38.447 回答
1

正如Judah指出的那样,单独使用泛型类型是不可能的。我找到了一种解决方法,我在其中发送了一个带有类型的参数...

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;
}

用法:

var numbers = OfType<any, number>(list, Number);
var foos = OfType<any, Foo>(list, Foo);

alert("Numbers: " + numbers);
alert("Foos: " + foos);

少量冗余,如果有人知道删除这种冗余的方法,请发表评论或编辑此代码。

或者,对于原始类型,我只能filter像 Judah 提到的那样使用。

于 2013-06-30T20:00:34.433 回答