Quantcast
Channel: Active questions tagged svelte - Stack Overflow
Viewing all articles
Browse latest Browse all 1541

Generic type recognized as "any". How can my generic type be improved?

$
0
0

Edit: Solved. Answer edited below

I would like to create a Svelte dropdown component that accepts multiple kinds of possible items<MySelect options={...}. I've considered several possibilities:

  1. Simplest: Raw string value. The "text" of the dropdown item is the same as the valueoptions=["Item 1", "Item 2", "Item 3"]

  2. Customizable text vs labeloptions=[{text: string, value: anything}, {...}]

  3. Grouped + Simplest. Grouped select

    options=[  { text: "Group 1", options: ["Item 1", "Item 2", ...]}
  4. Grouped + Customizable

    options=[  { text: "Group 1", options: [{text: string, value: anything}, {...}]}

I have come up with:

/** * Definitions for a single item in the list. */export type SimpleOption = string;export type LabeledSimpleOption<T> = { text: string; value: T };export type Option<T> = SimpleOption | LabeledSimpleOption<T>;export type GroupedOption<T> = { text: string; options: Array<Option<T>> };/** * Definitions for an array of items. */export type SimpleOptions<T> = Array<Option<T>>;export type GroupedSimpleOptions<T> = Array<GroupedOption<T>>;export type Options<T> = Option<T> | GroupedOption<T>;

Expectations:

  • Would be great to not have to specify the type.

  • Would be great if it could be inferred automatically

    let options: Options<string> = [  {    text: "Group 1",    options: [      { value: "1", text: "One" },  // OK      { value: "2", fsfsd: "Two" }, // Not OK      { value: "3", text: 3 },      // Not OK    ]  }];let options: Options<string> = ["Item 1", "Item 2"] // OKlet options: Options<number> = [1, 2] // NOT OKlet options: Options<number> = [    { value: "1", text: 1 },   // OK    { value: "2", fsfsd: 2 },  // Not OK    { value: "3", text: "3" }, // Not OK]

    Currently let options: Options<string> acts as if options had "any" as a type. I can assign anything and it's going to be accepted.

  • I need to be able to type the value returned as well as a single option itself.

    const items = [...]; // Assuming items signature is compatible with Options<T><MySelect  options={items}  valueAsItem={false} // Meaning item value is Items[i].value  itemSelect={(selectedItem) => ...} // selectedItem must be of type Items[i].value<MySelect  options={items}  valueAsItem={true} // Meaning item value is the item itself: Items[i]  itemSelect={(selectedItem) => ...} // selectedItem must be of type Items[i]
  • Later I would like to be able to dynamically set the label/value attribute name using props. Meaning

    let items = [    { attr: "1", label: 1 },    ...]<MySelect  options={items}  valueAsItem={true}  labelField="label"  valueField="attr"  itemSelect={(selectedItem) => ...} // selectedItem would be "1" (type of string)

I'm wondering if it is even possible to achieve everything in TypeScript or if I should rely on any type instead.

Edit 1

Edit: I have been requested to provide "working" demonstration code.I didn't mean to go so far as to involve Svelte/Components code asthe question is purely a Typescript challenge. I've created a Svelte playground for the demonstration.Type: src/types/MySelect.d.tsUsage: src/routes/+page.svelteURL: https://codesandbox.io/p/devbox/svelte-dropdown-test-mq3tpp

Viewing all articles
Browse latest Browse all 1541

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>