我有一個將有欄位的物件products,該欄位將填充由不同端點回傳的回應,每個端點回傳一種產品型別。就像是:
const products = {
// each of this kind of products comes from endpoint response
someProduct: {},
someOtherProduct: {}
anotherProduct: {}
}
所有產品型別都有一些共同的屬性,例如名稱、描述、價格。但它們也具有僅適用于一種產品的特定屬性。在某些情況下,我需要遍歷所有產品以呈現這些通用屬性的串列,但其他時候我需要為每種型別的產品呈現特定資料。
product如果這個物件包含不同的產品型別,每個產品型別都有不同的屬性并且來自外部資料源(服務器),我該如何輸入?
編輯 1:產品型別
每個產品都有一個屬性type,用于標識每個產品型別
編輯 2:選定的產品型別
當我在串列中呈現所有產品時,用戶可以單擊其中任何一個并將所選產品存盤在變數中...因此我可以使用所選產品列印特定產品詳細資訊...如何鍵入所選產品,是否可以是任何型別的產品?
uj5u.com熱心網友回復:
根據您對兩個(非常好的)答案的后續評論來判斷,其中您詢問在運行時(即當用戶選擇產品時)輸入未確定的產品型別時,您需要使用型別保護:
// here’s the type guard for one type, you’ll need one for all six; we’re checking against your `type` property but it could be anything
const isMyProductType = (obj: any): obj is MyProductType => obj.type === “myProductType”;
const onClick = (selectedProduct) => {
if (isMyProductType(selectedProduct)) {
// TS now will treat selectedProduct as an object of MyProductType
// do stuff
} else if (/* another type guard etc … */) {
// etc
}
}
uj5u.com熱心網友回復:
更新
您還可以在 CodeSandbox 中查看一個作業示例:使用陣列和選定的產品,以及所有其他內容:https ://codesandbox.io/s/condescending-sea-53xh8?file=/src/App.tsx
原來的
您可以執行以下操作:
在這種情況下,我們為所有公共屬性定義了一個 BaseProduct。我們擴展此產品介面以定義其他每個介面。
然后,我們定義一個型別Product,它可以是Product之前定義的任何型別的介面。
最后,我們可以定義的陣列Product(如果你的服務器的答案與陣列)或物件,可以有任何字串作為key和Product作為值。
interface BaseProduct {
name: string;
description: string;
price: number;
type: string;
}
interface SomeProduct extends BaseProduct {
genericAttrOne: string;
genericAttrTwo: string;
}
interface OtherProduct extends BaseProduct {
anAttributeOne: string;
anAttributeTwo: string;
}
interface AnotherProduct extends BaseProduct {
anotherAttributeOne: string;
anotherAttributeTwo: string;
}
type Product = SomeProduct | OtherProduct | AnotherProduct;
const productsAsArray: Product[] = [];
const productsAsObject: { [key: string]: Product }: {};
uj5u.com熱心網友回復:
以下是強輸入您描述的回應的示例:
TS 游樂場鏈接
// Start with the base product, defining the common properties
type Product<
T extends string = string,
P = Record<never, never>,
> = P & {
type: T;
name: string;
description: string;
price: number;
};
// Then define each product's specific type and properties
type SomeProduct = Product<'some', {
someValue1: string;
someValue2: number;
}>;
// For every product
type AnotherProduct = Product<'another', {
anotherValue1: string;
anotherValue2: number;
}>;
// Then assign them all to properties in an object of known products
type KnownProducts = {
some: SomeProduct;
another: AnotherProduct;
// etc...
};
// Create a type for known products any generic product with common properties
type AllProducts = KnownProducts & { [key: string]: Product };
declare const products: AllProducts;
products.some.name // ok
products.another.name // ok
products.some.type // "some"
products.some.someValue1 // ok
products.some.anotherValue1 // property doesn't exist
products.another.type // "another"
products.another.someValue1 // property doesn't exist
products.another.anotherValue1 // ok
// All other products will only have the commoon properties
products.mysteryProduct.name; // ok
// Narrowing a product type:
type KnownProduct = KnownProducts[keyof KnownProducts];
type AnyProduct = KnownProduct | Product;
function doSomethingWithAProduct (product: AnyProduct): void {
// explicitly handle cases for known products using an assertion, and the reference `p`
const p = product as KnownProduct;
switch (p.type) {
case 'some': {
p.type // "some"
p.name // ok
p.someValue1 // ok
p.anotherValue1 // Error: Property doesn't exist
break;
}
case 'another': {
p.type // "another"
p.name // ok
p.someValue1 // Error: Property doesn't exist
p.anotherValue1 // ok
break;
}
// in the default case use the argument `product` (which is still AnyProduct)
default: {
product.name;
break;
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/372371.html
標籤:javascript 反应 打字稿
上一篇:將列舉轉換為具有值的物件
下一篇:根據選定的復選框禁用欄位
