在泛型类型上进行过滤

6

我正在尝试使用TypeScript编写一个函数,该函数将允许我根据对象类型过滤列表。结果应该是一个函数,使我能够执行以下操作:

filter<Foo>(items);

或者

filter(items, Foo);

我一直在尝试以下方法进行操作:
class Foo {
    public constructor(public name: string, public type: string) {

    }
}

class Bar extends Foo { }

const items: Foo[] = [
    new Foo('Foo', 'A'),
    new Bar('bar', 'A'),
    new Foo('baz', 'B'),
];

const filter = <T extends Foo>(items: any[], typeT: T): T[] => {
    return items.filter(item => item instanceof typeT)
};

console.log(filter(items, Foo));

但是这个方法不起作用。

我该如何让它起作用?

TypeScript示例

2个回答

5

当你传入类型时,实际上是传入了类的构造函数。你的签名正在传递 T 的一个实例。你应该尝试:

const filter = <T extends Foo>(items: any[], typeT: new (...params : any[]) => T): T[] => {
    return items.filter(item => item instanceof typeT)
};

注意:在您的示例中,数组中的所有项都将通过过滤器,因为Bar派生自Foo,因此也是Foo的实例。如果您只想要Foo类型的对象而不是派生的对象,则可以使用item.constructor == typeT


也可以不使用类引用,而只使用类型来做类似的事情吗?例如,类型将是“Foo”,而不是实例。 - Robin_f
我不确定我理解这个问题。调用这个方法会是什么样子? - Titian Cernicova-Dragomir

0
你可以通过使用类的 name 属性来简化事情:
class Foo {
    public constructor(public name: string, public type: string) {

    }
}

class Bar extends Foo { }

const items: Foo[] = [
    new Foo('Foo', 'A'),
    new Bar('bar', 'A'),
    new Foo('baz', 'B'),
];

const filter = (items: Foo[], typeT: Function): Foo[] => {
    return items.filter(item => item.constructor.name === typeT.name)
};

console.log(filter(items, Foo)); // Array [ {…}, {…} ]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接