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

Sco*_*mas 3 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
})

Run Code Online (Sandbox Code Playgroud)

我想出的唯一解决方案是投射过滤后的数组:

type Foo = typeof foo;

const filteredArr = arr.filter(val => val.type === 'foo') as Foo[];
Run Code Online (Sandbox Code Playgroud)

但似乎应该有一种打字稿足够聪明的方式来推断数组已被过滤为仅Foo[].

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

Tit*_*mir 5

首先,fooand的类型bar应该保留文字类型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
Run Code Online (Sandbox Code Playgroud)

游乐场链接

不确定它是否比断言好很多,但不幸的是,这与你所能得到的一样接近。