【问题标题】:How to define filtered array in TypeScript如何在 TypeScript 中定义过滤后的数组
【发布时间】:2021-08-09 13:14:11
【问题描述】:

我有一个包含两个可能值的数组。它可能包括一个预期的对象,或者一个定义错误的对象。数据可能如下所示:

// mixedData
[
    { item1: "value", item2: "value2" },
    { error: true, description: "no value found" },
];

我为这个数组制作了两种类型。一个用于有效对象,一个用于错误对象。然后我像这样定义我的数组:

const myArray: Array<IValid | IError> = [] // fetched from api

接下来我想从数组中删除每个带有错误字段的对象,只留下IValid 对象:

const filteredData: IValid[] = mixedData.filter(
    (obj: IValid | IError) => !obj.hasOwnProperty("error")
);

这可行,但 TypeScript 并不喜欢这样,因为它仍然认为一个项目可能是 IError

Error: Type '(IValid| IError)[]' is not assignable to type 'IValid[]'.

如何让 TypeScript 在这里快乐?

【问题讨论】:

    标签: javascript typescript typescript-generics


    【解决方案1】:

    Type Guards 的简单示例

    interface IValid { item1: string; item2: string };
    interface IError { error: boolean; description: string };
    
    const data: Array<IValid | IError> = [
        { item1: "value", item2: "value2" },
        { error: true, description: "no value found" },
    ];
    
    function isValid(obj: IValid | IError): obj is IValid {
        return (obj as IError).error === undefined;
    }
    
    const filteredValidData = data.filter(isValid);
    console.log(filteredValidData);
    // [ { item1: "value", item2: "value2" } ]
    
    

    来自documentation的其他示例

    【讨论】:

      【解决方案2】:

      您可以将 typeguard 用作 filter 谓词:

      type IValid = { item1: string, item2: string }
      
      type IError = { error: boolean, description: string }
      
      type All = IValid | IError
      
      const data: All[] = [
          { item1: 'value', item2: 'value2' },
          { error: true, description: 'no value found' }
      ]
      
      const myArray: Array<IValid | IError> = [] // fetched from api
      
      const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
          : obj is Obj & Record<Prop, unknown> =>
          Object.prototype.hasOwnProperty.call(obj, prop);
      
      const filteredData = data.filter((obj): obj is IValid /** here is the trick */ => !hasProperty(obj, 'error')); // IValid[]
      

      Playground

      Object.prototype.hasOwnProperty.callobj.hasOwnProperty 安全得多,请参阅eslint rule

      【讨论】:

        【解决方案3】:

        只需转换为 validData[]。

        const filteredData: validData[] = mixedData.filter((obj: IValid | IError) => !obj.hasOwnProperty('error')) as validData[];
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-08-28
          • 2021-05-29
          • 2019-01-23
          • 1970-01-01
          • 2018-01-27
          • 1970-01-01
          • 2019-01-31
          • 2015-03-16
          相关资源
          最近更新 更多