【问题标题】:How to I specify a method filtering an array for a certain type of element?如何为某种类型的元素指定过滤数组的方法?
【发布时间】:2019-09-27 08:16:28
【问题描述】:

我正在尝试实现一个函数,它将由不同元素组成的数组拆分为特定类型的元素数组(在函数调用中指定)。这是简化的代码:

export enum GenericElementType {
  ONE = 'type one',
  TWO = 'type two'
}

export interface TypeA {
  id: string;
  type: GenericElementType.ONE;
}

export interface TypeB {
  id: string;
  type: GenericElementType.TWO;
}

export type ElementType = TypeA | TypeB;
const arrayOfElements: (DFDElementType)[] = [];

function filterElementsOfCertainType<T extends ElementType>
  (elements: (ElementType)[], type: GenericElementType): T[] {
  return elements.filter((element: ElementType) => element.genericType === type);
}

这会导致错误,因为并非ElementType 中的每个元素都与返回类型T 匹配。我将如何实现正确键入的此功能?

这是一个Playground 链接。

另一个使用泛型类型的Playground link

【问题讨论】:

标签: typescript typescript-typings


【解决方案1】:

假设您的“特定类型”是您提供的,返回 ElementType[],并将 element.type 与类型进行比较。认为这应该有效。干杯

编辑:

我认为你应该考虑一下模式。从你的最后一个游乐场。 elementOfTypeA: TypeA[] 应该是 elementOfTypeA: ElementType[],你已经给出了所需的类型作为参数。用更简单的逻辑来说,这永远行不通:

interface  person{
  id: string;
}
type teacher = person | number;

const randomVariable: person = 3;

虽然,这会:

interface  person{
  id: string;
}
type teacher = person | number;

const randomVariable: teacher = 3;

最后的手段:

function filterElementsOfCertainType<T extends ElementType>
  (elements: any[], type: GenericElementType): T[] {
  return elements.filter((element: T) => element.type !== undefined && element.type === type);
}

然后 const elementOfTypeA: TypeA[] = filterElementsOfCertainType([a, b, c], GenericElementType.TWO);将工作。

这似乎也是打字稿文档希望您这样做的方式。 https://www.typescriptlang.org/docs/handbook/advanced-types.html

选中“用户定义的类型保护”。干杯伙伴。

playground

【讨论】:

  • 如果我这样做,我会得到所需的元素类型,但是我会遇到分配正确类型变量的问题。例如: const elementsOfTypeA: TypeA[] = this.filterElementsofCertainType(elements, GenericElementType.ONE) 将导致错误。
  • 也许我误解了你的意思,但这似乎与我的问题不相似。我有一个包含两种不同类型元素的数组。现在我想过滤那个数组,只返回一种元素。然后我希望能够为返回值分配一个变量,该值被键入到两个可能的元素之一。
  • 添加了一个游乐场,认为这应该可以解决您的问题。也不会给你一个错误。
  • 可以,非常感谢您的帮助!不是 100% 售出 any[] 类型的元素数组,但我猜这里的类型安全问题可以通过 element.type === type 检查得到缓解。
【解决方案2】:

这个playground 应该可以工作。但是,这是正确的输入:

function filterElementsOfCertainType<T extends ElementType>
  (elements: T[], type: GenericElementType): T[] {
  return elements.filter((element: T) => element.type === type);
}

【讨论】:

  • 是的,代码有效。但问题仍然存在 - 如果传递的数组被键入为三种可用元素类型之一,则它是不可分配的。我为我的问题附加了另一个游乐场链接,以更好地说明我的意思。
  • const elementOfTypeA: TypeA[] = filterElementsOfCertainType([a, b, c], GenericElementType.TWO) as TypeA[];
  • 这行得通,但这会一起消除类型安全性 - 例如传递GenericElementType.ONE 不会导致错误。
猜你喜欢
  • 2014-08-09
  • 1970-01-01
  • 2023-03-26
  • 2020-09-12
  • 2017-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多