首页 > 解决方案 > 将工厂创建的对象推送到数组时更正类型声明

问题描述

在打字稿中,如果我有一个工厂方法可能会根据运行时值生成不同的对象。如何声明创建的对象的结果数组是一种类型或另一种类型,而不是两者?

interface Foo {
    fooProp: 'Foo'
}

interface Bar {
    barProp: 'Bar'
}

function barFactory(): Bar {
    return { barProp: 'Bar' }
}

function fooFactory(): Foo {
    return { fooProp: 'Foo' }
}

let factory: (() => Foo) | (() => Bar);

let someRuntimeValue = true;
if (someRuntimeValue) {
    factory = fooFactory;
} else {
    factory = barFactory;
}

let objects: Foo[] | Bar[];
for (let n = 0; n < 10; ++n) {
    //TS - Argument of type 'Foo | Bar' is not assignable 
    //to parameter of type 'Foo & Bar'.
    objects.push(factory()); 
}

标签: typescript

解决方案


如果它不是运行时值,您可能会使用模板(只要您的代码被封装在函数、类或接口中),但是因为它是一个变量,所以您必须使用该as any短语来制作编译器在您的代码中“忽略它”,如下所示:

let objects: Foo[] | Bar[];
for (let n = 0; n < 10; ++n) {
    objects.push(factory() as any); // ignore the `Foo | Bar` return type
}

在 typescript 中,尤其是在做这样的事情时,你必须经常使用这个as any短语——只要确保你做的事情正确,因为编译器在这里跳过类型检查。

例如,也许稍后您想将其传递给仅处理Foo[]类型的函数;你将不得不在那里使用类似的东西:

function testFoo(objects: Foo[]) {
  return !objects.find(a => !(a.fooProp));
}

if(someRuntimeValue) {
  testFoo(objects as Foo[]);
}

推荐阅读