Typescript 将工厂创建的对象推送到数组时更正类型声明

Typescript 将工厂创建的对象推送到数组时更正类型声明,typescript,Typescript,在typescript中,如果我有一个工厂方法,它可能根据运行时值生成不同的对象。如何声明所创建对象的结果数组是一种类型还是另一种类型,而不是两种类型 interface Foo { fooProp: 'Foo' } interface Bar { barProp: 'Bar' } function barFactory(): Bar { return { barProp: 'Bar' } } function fooFactory(): Foo { ret

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

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()); 
}
接口Foo{
fooProp:‘Foo’
}
接口条{
酒吧道具:“酒吧”
}
函数barFactory():Bar{
返回{barProp:'Bar'}
}
函数fooFactory():Foo{
返回{fooProp:'Foo'}
}
让工厂:(()=>Foo)|(()=>Bar);
让someRuntimeValue=true;
if(someRuntimeValue){
工厂=食品工厂;
}否则{
工厂=酒吧工厂;
}
让对象:Foo[]| Bar[];
对于(设n=0;n<10;++n){
//TS-类型为“Foo | Bar”的参数不可赋值
//到类型为“Foo&Bar”的参数。
push(factory());
}

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

let对象:Foo[]| Bar[];
对于(设n=0;n<10;++n){
objects.push(factory()如有);//忽略'Foo | Bar'返回类型
}
在typescript中,尤其是在执行类似操作时,您必须将
用作任何
短语——只需确保操作正确,因为编译器将跳过此处的类型检查

例如,以后可能希望将其传递给只处理
Foo[]
类型的函数;您必须使用类似的工具:

函数testFoo(对象:Foo[]){ return!objects.find(a=>!(a.fooProp)); } if(someRuntimeValue){ testFoo(对象为Foo[]); }
如果它不是一个运行时值,您可能会使用模板(只要您的代码被封装在函数、类或接口中),但由于它是一个变量,您必须使用
作为任何
短语,使编译器在代码中“忽略它”,如下所示:

let对象:Foo[]| Bar[];
对于(设n=0;n<10;++n){
objects.push(factory()如有);//忽略'Foo | Bar'返回类型
}
在typescript中,尤其是在执行类似操作时,您必须将
用作任何
短语——只需确保操作正确,因为编译器将跳过此处的类型检查

例如,以后可能希望将其传递给只处理
Foo[]
类型的函数;您必须使用类似的工具:

函数testFoo(对象:Foo[]){ return!objects.find(a=>!(a.fooProp)); } if(someRuntimeValue){ testFoo(对象为Foo[]); }
Array
?我想要一个或另一个,尽管
Foo[]| Bar[]
不是
[Bar,Foo,Foo,Bar,…]
好吧,我不确定,让我们看看是否有人提出建议。
Array
我想要一个或另一个,尽管
Foo[]| Bar[/code>不是
[Bar,Foo,Foo,Bar,
好吧,我不确定,让我们看看是否有人提出了建议。您的代码没有什么意义:每个
对象
项都有一个
Foo&Bar
类型(OPs代码中没有一个类型满足它)。实际上,在这里使用
作为any
并不能更好地将
对象声明为
any
,而完全不使用任何类型。恐怕你错了:如果要遵循
工厂()
返回类型,则
对象的每个项都有
Foo | Bar
类型。在这段代码中,
对象
仍然保留其类型定义,而我们仅在特定情况下绕过它。因为它保留了它的类型定义(不管它有多僵硬),我们可以在以后保留某种形式的类型检查,并按照第二个示例所示进行操作。您自己检查一下如何“仍然保留它的类型定义”——正如我指出的,如果您单击上面的链接,您将看到一个无意义的不存在的交叉点类型。如果您将其声明为
Array
正确,那么它将具有
Foo | Bar
类型——类型定义确实非常不灵活——但它并非毫无意义。我们知道类型不是一个就是另一个——因此,每次OP想要处理
对象
变量时,他们必须确定类型(使用
someRuntimeVariable
)并将
转换为
关键字,或者将其视为不灵活的交集类型;我相信这就是他们想要的。你的代码没有什么意义:每一个
对象
都有一个
Foo&Bar
类型(并且OPs代码中没有一个类型满足它)。实际上,在这里使用
作为any
并不能更好地将
对象声明为
any
,而完全不使用任何类型。恐怕你错了:如果要遵循
工厂()
返回类型,则
对象的每个项都有
Foo | Bar
类型。在这段代码中,
对象
仍然保留其类型定义,而我们仅在特定情况下绕过它。因为它保留了它的类型定义(不管它有多僵硬),我们可以在以后保留某种形式的类型检查,并按照第二个示例所示进行操作。您自己检查一下如何“仍然保留它的类型定义”——正如我指出的,如果您单击上面的链接,您将看到一个无意义的不存在的交叉点类型。如果您将其声明为
Array
正确,那么它将具有
Foo | Bar
类型——类型定义确实非常不灵活——但它并非毫无意义。我们知道类型不是一个就是另一个——因此,每次OP想要处理
对象
变量时,他们必须确定类型(使用
someRuntimeVariable
)并将
转换为
关键字,或者将其视为不灵活的交集类型;