首页 > 解决方案 > “未知”类型的参数不能分配给“{}”类型的参数

问题描述

这是我的代码

 const Res = await fetch(`https://foo0022.firebaseio.com/.json`);
        const ResObj = await Res.json();
        if (!Res.ok || !ResObj) { 
          throw new Error("Page Not Found 404");
        } 
        const ResArr = await Object.values(ResObj)
            .map(v => Object.values(v).flat())//error
            .flat()
            .filter(({ title }) => title.includes(Search))

在该行中,我收到此错误“.map(v => Object.values(v).flat())”我收到此错误“未知”类型的参数不可分配给“{}”类型的参数.如何解决这个问题?

标签: reactjstypescript

解决方案


这里的问题是你需要帮助 TypeScript 理解你正在处理的对象的类型。fetchAPI 无法提前知道返回的对象的形状是什么,所以你必须定义它并断言他的结果符合它。

查看https://foo0022.firebaseio.com/.json的内容,我建议如下:

interface ResObj {
  Mens: {
    Hat: Clothing[];
    Jacket: Clothing[];
    Pants: Clothing[];
    Shoes: Clothing[];
    Suit: Clothing[];
  };
  New: Clothing[];
}
interface Clothing {
  agility: boolean[];
  alt: string;
  color: string[][];
  id: string;
  location?: string; // fix this
  Location?: string; // fix this
  material: string;
  price: string[][];
  prodState: string;
  saiz: string[][];
  shipping: string;
  sold: string;
  src: string[][];
  title: string;
  to: string;
}

但当然,这是否准确取决于某种 API 文档。假设这是对的,你可以走得更远一点:

  const Res = await fetch(`https://foo0022.firebaseio.com/.json`);
  const ResObj: ResObj | undefined = await Res.json();
  if (!Res.ok || !ResObj) {
    throw new Error("Page Not Found 404");
  }

现在ResObj将被称为类型ResObj,您可以开始操作它。一个问题是标准库的类型Object.values()Array.prototype.flat()不能反映你正在用它们做什么。我们可以为它们构建一些自定义类型......但在这种情况下,我将使用类型匹配的新函数包装它们:

  // return an array of all object values...
  // if the object is already an array, the output is the same type.
  // otherwise it's the union of all the known property types
  function vals<T extends object>(
    arr: T
  ): Array<T extends Array<infer U> ? U : T[keyof T]> {
    return Object.values(arr); // need es2017 lib for this
  }

  // Flatten an array by one level... 
  function flat<T>(
    arr: Array<T>
  ): Array<Extract<T, any[]>[number] | Exclude<T, any[]>> {
    return arr.flat(); // need esnext lib for this
  }

如果您以前从未使用过 TypeScript,那么这些函数类型可能会令人困惑,尤其是因为它们依赖条件类型来梳理数组属性。

然后我们可以像这样重写你的代码:

  const ResArr = flat(vals(ResObj).map(v => flat(vals(v)))).filter(
    ({ title }) => title.includes(Search)
  );

并且没有错误,编译器理解这ResArr是一个Clothing对象数组。

链接到代码

好的,希望有帮助;祝你好运!


推荐阅读