Skip to main content

๐Ÿ“ฆ FetchProductVariantResult

TypeScript interface defining the return value structure of the getProductVariant() function.


๐Ÿ“‹ Interface Definitionโ€‹

interface FetchProductVariantResult {
variant: ProductVariant;
product: Product;
error: string | null;
}

๐Ÿ” Propertiesโ€‹

variantโ€‹

  • Type: ProductVariant
  • Description: The specific variant data with requested fields and metafields
  • Always present: Yes (null if error)

productโ€‹

  • Type: Product
  • Description: Complete product context for the variant
  • Always present: Yes (null if error)

errorโ€‹

  • Type: string | null
  • Description: Error message if the fetch failed
  • Null when: Fetch was successful

ProductVariantโ€‹

interface ProductVariant {
id: string; // Always included
title: string; // Always included

// Additional fields (when requested via variantFields)
price?: {
amount: number;
currencyCode: string;
};
compareAtPrice?: {
amount: number;
currencyCode: string;
} | null;
availableForSale?: boolean;
selectedOptions?: Array<{
name: string;
value: string;
}>;
image?: Image | null;
sku?: string;
barcode?: string;
weight?: number;
weightUnit?: string;
requiresShipping?: boolean;
taxable?: boolean;
inventoryQuantity?: number;
inventoryPolicy?: string;

// Metafields (when requested)
metafields: Record<string, any>;
}

Productโ€‹

interface Product {
id: string; // Always included
title: string; // Always included
handle: string; // Always included

// Additional fields (when requested via productFields)
vendor?: string;
productType?: string;
tags?: string[];
descriptionHtml?: string;
description?: string;
images?: Image[];
featuredImage?: Image | null;
variants?: ProductVariant[];
seo?: {
title?: string;
description?: string;
};
createdAt?: string;
updatedAt?: string;

// Metafields (when requested)
metafields: Record<string, any>;
}

Imageโ€‹

interface Image {
id: string;
url: string;
altText: string | null;
width: number;
height: number;
}

๐Ÿงช Usage Examplesโ€‹

Basic Result Handlingโ€‹

const { variant, product, error } = await getProductVariant({
variantId: "gid://shopify/ProductVariant/123456789",
});

if (error) {
console.error("Failed to fetch variant:", error);
return;
}

// variant and product are guaranteed to be present when error is null
console.log(`Variant: ${variant.title}`);
console.log(`Product: ${product.title}`);
console.log(`Handle: ${product.handle}`);

Accessing Additional Fieldsโ€‹

const result = await getProductVariant({
variantId: "gid://shopify/ProductVariant/123456789",
productFields: ["vendor", "images", "variants"],
variantFields: ["price", "availableForSale", "selectedOptions"],
});

if (!result.error) {
const { variant, product } = result;

// Access additional variant fields
console.log(`Price: $${variant.price?.amount}`);
console.log(`Available: ${variant.availableForSale}`);
console.log(`Options:`, variant.selectedOptions);

// Access additional product fields
console.log(`Vendor: ${product.vendor}`);
console.log(`Images: ${product.images?.length} images`);
console.log(`Total variants: ${product.variants?.length}`);
}

Working with Metafieldsโ€‹

const result = await getProductVariant({
variantId: "gid://shopify/ProductVariant/123456789",
productMetafields: [
{ field: "custom.brand", type: "single_line_text" },
{ field: "custom.warranty_years", type: "number_integer" },
],
variantMetafields: [
{ field: "custom.sku", type: "single_line_text" },
{ field: "custom.weight", type: "weight" },
],
options: {
camelizeKeys: true,
},
});

if (!result.error) {
const { variant, product } = result;

// Access product metafields (camelized)
const brand = product.metafields.customBrand;
const warranty = product.metafields.customWarrantyYears;

// Access variant metafields (camelized)
const sku = variant.metafields.customSku;
const weight = variant.metafields.customWeight;

console.log(`${brand} ${product.title}`);
console.log(`SKU: ${sku}, Weight: ${weight?.value}${weight?.unit}`);
console.log(`Warranty: ${warranty} years`);
}

Error Handlingโ€‹

const result = await getProductVariant({
variantId: "invalid-variant-id",
});

if (result.error) {
// Handle specific error cases
switch (result.error) {
case "Variant not found":
console.log("The variant doesn't exist");
break;
case "Access denied":
console.log("Check your access token permissions");
break;
default:
console.log("Unexpected error:", result.error);
break;
}
return;
}

// Safe to use variant and product
const { variant, product } = result;

Type Guardsโ€‹

function isValidResult(
result: FetchProductVariantResult
): result is { variant: ProductVariant; product: Product; error: null } {
return result.error === null;
}

const result = await getProductVariant({
variantId: "gid://shopify/ProductVariant/123456789",
});

if (isValidResult(result)) {
// TypeScript knows variant and product are not null
const variantTitle = result.variant.title;
const productHandle = result.product.handle;
}

Building UI Componentsโ€‹

interface VariantCardProps {
variantId: string;
}

async function VariantCard({ variantId }: VariantCardProps) {
const result = await getProductVariant({
variantId,
productFields: ["images", "vendor"],
variantFields: ["price", "availableForSale"],
productMetafields: [
{ field: "custom.brand", type: "single_line_text" },
],
});

if (result.error) {
return <div>Error loading variant: {result.error}</div>;
}

const { variant, product } = result;

return (
<div className="variant-card">
{product.images?.[0] && (
<img
src={product.images[0].url}
alt={product.images[0].altText || product.title}
/>
)}
<h3>{product.title}</h3>
<p>{variant.title}</p>
<p>${variant.price?.amount}</p>
<p>Brand: {product.metafields.customBrand}</p>
<p>Vendor: {product.vendor}</p>
<button disabled={!variant.availableForSale}>
{variant.availableForSale ? "Add to Cart" : "Sold Out"}
</button>
</div>
);
}

๐Ÿšจ Error Statesโ€‹

Common error messages you might encounter:

  • "Variant not found" - The variant ID doesn't exist
  • "Access denied" - Insufficient permissions for the access token
  • "Invalid variant ID format" - Malformed variant ID
  • "Product not found" - The variant exists but its product is unavailable
  • Network-related errors from the underlying fetch operation

โœ… Back to: Options Types โ†’