如何有条件地将对象添加到类型化值数组中

问题描述 投票:0回答:1

我正在尝试有条件地将对象添加到类型值数组,但收到错误 尝试使用扩展运算符或导出到函数:(

假设

interface Foo {
   type:'foo',
   cool: string,
}
interface Bar {
   type: 'bar'
   lame: string,
}

interface FooBar = | Foo | Bar


const arr: FooBar[] = [
   {
      type: 'foo',
      cool: 'this works great!',
   },
   ...(true &&         <---- Will through error Types of property 'type' are incompatible 'string' is not assignable to '"bar" | "foo"' 
      [
       {
          type: 'bar',
          lame: 'WHY THIS ERROR ON TYPE",
       }
      ]
     ),
]

有什么想法吗?

typescript types
1个回答
0
投票

除非有理由不这样做,否则 TypeScript 假定字符串文字的类型为

string
。在您的问题中,第一个对象 isn't 会以这种方式处理,因为它立即存储在一个数组中,其中字符串文字类型
"foo"
有效,但
string
无效。

那么为什么你的第二个对象没有得到同样的处理呢?因为它不会立即在 TypeScript 可以应用它的上下文中使用。它是表达式 (

true && {/*...*/}
) 的一部分,因此
type
属性仅键入为
string
,并且不能分配给文字类型
"foo"
"bar"

您可以通过将

as const
添加到您正在传播的数组中来修复它,因为这告诉 TypeScript 该属性不会被重新分配,因此它可以保持其最窄的类型(在本例中为
"bar"
):

interface Foo {
   type:'foo',
   cool: string,
}
interface Bar {
   type: 'bar'
   lame: string,
}

type FooBar = | Foo | Bar

const arr: FooBar[] = [
   {
      type: 'foo',
      cool: 'this works great!',
   },
   ...(true && 
      [
       {
          type: 'bar',
          lame: 'WHY THIS ERROR ON TYPE',
       }
      ] as const // <====
     ),
]

游乐场链接

(注意,我还必须修复几个语法错误。您不能使用

interface FooBar =
,所以我使用
type
代替,并且
lame
属性上的结束引号并不相同就像它的开场白一样。)

© www.soinside.com 2019 - 2024. All rights reserved.