【问题标题】:How pass an object to a child custom React functional component with Typescript如何使用 Typescript 将对象传递给子自定义 React 功能组件
【发布时间】:2021-07-10 09:18:20
【问题描述】:

感谢您花时间阅读本文。

我正在尝试使用带有 AirBnB 配置的 eslint 来学习 Typescript。像映射一组对象并为每个对象创建一个自定义功能组件这样简单的事情给了我下一个错误:

Argument of type '(product: ProductType) => JSX.Element' is not assignable to parameter of type '(value: object, index: number, array: object[]) => Element'.

这里是父组件ProductGrid:

const ProductGrid: React.FC = () => {
  const products = [
    {
      id: "string1",
      name: "string1",
      price: {
        formatted_with_symbol: "string1"
      },
      description: "string1",
    },
    ...
  ];

  return (
    <div>
      <Grid container spacing={3}>
        <Grid item xs={12} md={6} lg={4}>
          {products.map((product: ProductType) => (
            <Product key={product.id} product={product} />
          ))}
        </Grid>
      </Grid>
    </div>
  );
};

export default ProductGrid;

这是子组件Product:

const Product: React.FC<ProductTypeAsProps> = ({product}: ProductTypeAsProps) => {
 const [loading, setLoading] = useState(true);
 setTimeout(() => {
      setLoading(false);
    }, 3000);
  
  return (
    <Box className="product">
      <Card className="card">
        <CardContent className="content">
          {loading ? (
            <div className="skeleton">
              <Skeleton
                variant="text"
                animation="wave"
                component="h2"
                width="65%"
              />
            </div>
          ) : (
            <div>
              <p>{product.name}</p>
              <p>{product.description}</p>
              <p>{product.price.formatted_with_symbol}</p>
            </div>
          )}
        </CardContent>
      </Card>
    </Box>
  );
};

export default Product;

以及类型声明:

export type ProductType = {
  id: string;
  name: string;
  price: {
    formatted_with_symbol: string;
  };
  description: string;
  assets: [
    {
      id: string;
      filename: string;
      url: string;
    }
  ];
};

export interface ProductTypeAsProps {
  product: ProductType;
}

我也有一个 .eslintrc :

{
  "extends": ["airbnb-typescript", "react-app", "prettier"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "sourceType": "module",
    "project": "tsconfig.json"
  },
  "plugins": ["prettier", "@typescript-eslint", "react-hooks"],
  "settings": {
    "import/resolver": {
      "typescript": {
        "alwaysTryTypes": true
      }
    }
  },
  "rules": { 
    "@typescript-eslint/no-explicit-any": [
      "error",
      {
        "ignoreRestArgs": true
      }
    ],
  }
}

和 tsconfig :

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["es6", "dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "noImplicitAny": false
  },
  "include": ["src"]
}

我已经创建了this codesandbox,但当然,lint 错误并没有出现在那里,我在 VsCode 中对此进行了编码。

有什么帮助吗?因为这在 javascript 中是相当标准的。

【问题讨论】:

  • 我应该提到这是从 commerce.js 中提取的,这意味着我从后端收到的 product 对象要大得多,但到目前为止我只使用类型化的属性。我相信这没问题。

标签: reactjs typescript eslint eslint-config-airbnb


【解决方案1】:

我可以通过查看错误消息来判断问题所在:

'(product: ProductType) => JSX.Element' 类型的参数不能分配给'(value: object, index: number, array: object[]) => Element' 类型的参数。

这表示您在products.map() 中使用的映射函数是(product: ProductType) =&gt; JSX.Element 类型。它说这不是您的products 数组的有效映射器,因为products.map() 需要(value: object, index: number, array: object[]) =&gt; Element 类型的映射函数。

为什么会这样?
此错误意味着您的实际代码中的products 变量的类型为object[]。您正试图通过在 map() 中使用 (product: ProductType) 来弥补这种模糊类型,但这不起作用。在此处输入参数意味着您的 map 函数只能处理 ProductType 类型的对象,但它需要处理任何 object,因为 productsobject 的数组。

您需要做的是使您的products 变量具有ProductType[] 类型。我认为您是从实际代码中的 API 获取这些数据的?因此,请确保 API 调用返回 ProductType[] 而不是 object[]

作为一种快速修复,您可以在映射数组之前断言数组的类型,但最好从源头解决问题。

{(products as ProductType[]).map((product) => (
  <Product key={product.id} product={product} />
))}

【讨论】:

  • 你是一个神圣的天才!!!我仍然无法理解这些错误的含义。你是后端类型的现货。我正在使用 redux,所以我有一个初始状态的本地类型,如果产品确实是 object[],我后来定义了实际的 ProductType。感谢@LindaPaiste 让它如此清晰!! :D
猜你喜欢
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 1970-01-01
  • 2021-04-29
  • 2021-01-26
  • 2020-03-12
  • 2020-09-05
相关资源
最近更新 更多