Conflicting Requirements for `key` Prop on `<s-option>` in Iterables

There is a conflict between my linter and TypeScript type definitions for the <s-option> component when used in iterables. Th linter requires a key prop for elements in iterables, but adding the key prop causes a TypeScript error because the OptionJSXProps type does not include a key property.

Environment

  • Extension Type: Admin Extension
  • Framework: Preact ^10.10.x
  • TypeScript: ^5.8.3
  • Shopify CLI: ^3.80.7
  • @shopify/ui-extensions: ~2025.10.0-rc
  • Node.js: 22.x
  • pnpm: 8.15.4
  • Linter: Biome

Steps to Reproduce

  1. Use the following JSX in an admin extension:

    <s-select label="Example" name="example" value={value} onInput={handleChange}>
      {OPTIONS.map((opt) => (
        <s-option value={opt.value}>{opt.label}</s-option>
      ))}
    </s-select>
    
  2. Observe that Biome linter warns:

    Missing key property for this element in iterable.biomelint/correctness/useJsxKeyInIterable
    
  3. Add a key prop to <s-option>:

    <s-option key={opt.value} value={opt.value}>{opt.label}</s-option>
    
  4. Observe that TypeScript now errors:

    Impossible d'assigner le type '{ children: string | (string | bigint)[] | (string | false)[] | (string | true)[] | (string | object)[] | (string | VNode<any>)[]; value: string; key: string; }' au type 'OptionJSXProps & BaseProps'.
    La propriété 'key' n'existe pas sur le type 'OptionJSXProps & BaseProps'.ts(2322)
    

Expected Behavior

  • Either the Biome linter should not require a key prop for <s-option> in iterables, or the OptionJSXProps type should include a key property.

Actual Behavior

  • Biome linter requires a key prop, but TypeScript errors when the key prop is added.
  • This forces me to choose between ignoring the linter or ignoring the type error.
1 Like

Thanks for reporting this! We’re looking into it and will respond when we have more info.

(Note that I think you’ll have the same error if you try to use ref as well)

Hi @blanklob

This should be resolved now :slight_smile:

All good thanks! @Liam-Shopify

2 Likes