打字稿:条件类型的过滤器数组并具有正确的返回类型

时间:2019-11-15 18:09:56

标签: arrays typescript

我想过滤条件类型的数组,并具有正确的返回类型。例如,使用以下代码:

const foo = {
  type: "foo" as const,
  foo: 123
}

const bar = {
  type: "bar" as const,
  bar: 123
}

const arr = [foo, bar]

const filteredArr = arr.filter(val => val.type === 'foo');

filteredArr.map(val => {
  val.foo //Typescript blows up! Property foo does not exist on type
})

我想出的唯一解决方案是强制转换过滤后的数组:

type Foo = typeof foo;

const filteredArr = arr.filter(val => val.type === 'foo') as Foo[];

但是似乎应该有一种打字稿应该足够聪明,可以推断出数组仅被过滤为Foo[]

也许是用户定义类型防护的一些棘手用法?

1 个答案:

答案 0 :(得分:3)

首先,foobar的类型应保留type的文字类型,以便具有可区分的联合(假设您可能无论如何都具有类型别名或接口) 。

filter将采用自定义类型防护,但不幸的是无法从使用中推断出类型防护,因此函数val => val.type === 'foo'不会缩小类型的范围。

我们可以做的是显式注释函数,以使编译器知道我们正在缩小函数的类型:

const foo = {
  type: "foo" as const, // added to preserve ,
  foo: 123
} 

const bar = {
  type: "bar" as const, // added to preserve 
  bar: 123
} 

const arr = [foo, bar]

const filteredArr = arr.filter((val): val is typeof foo => val.type === 'foo')

filteredArr.map(x => x.foo) // ok

Playground Link

不确定它比断言要好得多,但是很不幸,这与声明很接近。