有没有办法要求T成为联合类型的成员?

时间:2015-01-28 09:23:32

标签: typescript

假设我有一个联合类型type Foo = Bar | Baz和一组foos(Array<Foo>)。有没有办法编写一个过滤函数,它以类型安全的方式从数组中只提取某种类型?

类似以下内容,但请指明T必须是Foo的成员。因此,例如onlyFoosOfType(x, Number)将不会进行类型检查。

class Bar {}
class Baz {}

type Foo = Bar | Baz;
var a: Array<Foo> = [];

function
onlyFoosOfType<T>
( arr  : Array<Foo>
, ctor : new(...args) => T
): Array<T> {
    return <Array<T>> arr.filter(x => {
        return x instanceof ctor;
    });
}

1 个答案:

答案 0 :(得分:1)

以下是一个完整的示例,它接受BarBaz,但拒绝我创建的其他类作为示例。

突出点是泛型类型约束:T extends Foo

TypeScript非常棒,可以接受联合类型,但不能接受其他类型...当然,如果它们在结构上完全相同(即,如果我创建了另一个看起来与Bar类完全相同的类或者类似于Baz类,这是允许的。这是有道理的,因为它也允许我在Array<Foo>中使用该类型。

class Bar {
    constructor(public num: number){}
}

class Baz {
    constructor(public num: number){}
}

class Example {

}

type Foo = Bar | Baz;
var a: Array<Foo> = [
    new Bar(1),
    new Baz(2),
    new Bar(3),
    new Bar(4)

];


function onlyFoosOfType<T extends Foo>(arr  : Array<Foo>, ctor : new(...args) => T): Array<T> {
    return <Array<T>><any> arr.filter(x => {
        return x instanceof ctor;
    });
}

var example1 = onlyFoosOfType(a, Bar);
// "[{"num":1},{"num":3},{"num":4}]"
console.log(JSON.stringify(example1));


var example2 = onlyFoosOfType(a, Baz);
// "[{"num":2}"
console.log(JSON.stringify(example2));

// Error: Example is not a Foo!
var example3 = onlyFoosOfType(a, Example);

为了证明这一点,这里是一个可以使用Example类的版本......

class Bar {
    constructor(public num: number){}
}

class Baz {
    constructor(public num: number){}
}

class Example {
    constructor(public num: number){}
}

type Foo = Bar | Baz;
var a: Array<Foo> = [
    new Bar(1),
    new Baz(2),
    new Bar(3),
    new Bar(4),
    new Example(5)
];

var example4 = onlyFoosOfType(a, Example);
// "[{"num":5}"
console.log(JSON.stringify(example4));