【问题标题】:How to use nested objects in TypeScript? Property does not exist on type 'object'如何在 TypeScript 中使用嵌套对象?类型“对象”上不存在属性
【发布时间】:2021-12-30 09:18:38
【问题描述】:

我有一个运行良好的 React/GraphQL 小型应用程序,我正在尝试向其中添加 TypeScript,因为我是 TypeScript 的新手并正在尝试学习它。我有一个 GraphQL API 端点,它返回产品和这些产品的信息。使用 React,我将产品存储在一个状态中,然后使用 JSX 渲染每个产品。

我创建了一个 Product 类型,其中包含我希望 API 返回的信息,但它也返回嵌套对象,并且我尝试的所有操作都会触发 TypeScript 错误。这是 API 返回内容的简化示例:

{
    "data": {
        "products": [
            {
                "productName": "Soda",
                "code": "sod",
                "prices": {
                    "nationalPrices": {
                        "localPrices": [
                            {
                                "pricePerUnit": "1.99"
                            }
                        ],
                        "regionalPrices": [
                            {
                                "pricePerUnit": "2.49"
                            }
                        ]
                    },
                    "vendorPrices": {
                        "localPrices": [
                            {
                                "pricePerUnit": "1.49"
                            }
                        ]
                    }
                }
            },
            // more products... 
        ]
    }
}

这是我目前拥有的解决方案。 codeproductNameprices 工作正常,但 nationalPrices 正在触发 TypeScript 错误 property nationalPrices does not exist on type 'object'。我该如何解决这个错误?

type nationalPricesObject = {
    localPrices: object[];
}

type Product = {
    code: string;
    productName: string;
    prices: object;
    nationalPrices: nationalPricesObject;
}


function ProductList() {
    const [products, setProducts] = useState < Product[] > ([]);
    const { loading, data, error } = useQuery(LOAD_PRODUCTS);

    useEffect(() => {
        if (data) {
            setProducts(data.products);
        }
    }, [data]);

    return (
        <>
            <div>
                {products.map(p =>
                (
                    <div>
                        <ProductCard
                            productName={p.displayName}
                            code={p.code}
                            // simplified code below for sake of clearity 
                            pricePerUnit={p.prices.nationalPrices.localPrices[0]['pricePerUnit']}
                        />
                    </div>
                ))}
            </div>
        </>
    )
}

【问题讨论】:

  • 旁注,你会喜欢的,在使用 GraphQl 时省去了打字稿类型的所有麻烦...npmjs.com/package/@graphql-codegen/cli
  • 在模板中,您引用的 product.prices.nationalPrices 根据您的上述类型不存在。你输入了Product.prices,只是一个普通的object。遵循@James 的回答将解决此问题。

标签: javascript reactjs typescript graphql


【解决方案1】:

产品不包含 nationalPrices 属性。 Product.prices 确实如此。我们可以设置一个价格类型,其中包含 Product.prices 中预期的内容,并使用它来定义 Product 对象的价格属性。

type Prices = {
    nationalPrices: nationalPricesObject;
    vendorPrices: someOtherPricesObject;
}

type Product = {
    code: string;
    productName: string;
    prices: Prices;
}

【讨论】:

    【解决方案2】:

    object 在打字稿中的使用很棘手,通常不推荐使用。你有两个问题:

    1. object 是一个模棱两可的类型,所以你不能使用 prices.nationalPrices 因为 nationalPrices 不存在于类型 object
    2. 修复此问题后,您还会遇到localPrices[0] 类型为object 的错误没有pricePerUnit

    要解决这些问题,请让您的类型更具体:

    type nationalPricesObject = {
        localPrices: { pricePerUnit: number; }[]; // assuming this is number?
    }
    
    type Product = {
        code: string;
        productName: string;
        prices: nationalPricesObject;
    }
    

    最后,按照惯例,typescript 中的类型应该是PascalCase,并且应该首选接口。因此,我会将您的代码更改为:

    interface Price {
      pricePerUnit: number;
    }
    
    interface NationalPrices {
        localPrices: Price[];
    }
    
    interface Product {
        code: string;
        productName: string;
        prices: NationalPrices;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-02-12
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 2020-02-24
      • 2019-10-11
      • 2018-02-10
      • 2018-03-03
      • 1970-01-01
      相关资源
      最近更新 更多