Skip to content

Idea: Variation helper type to extract a variant #23

@hellos3b

Description

@hellos3b

I've been rereading the docs as I switch over to variant@dev, and have a suggestion in reference to "That type annotation"

Complexity

The type has been a sore spot in using the library. Along with having to find and copy and paste the definition for each variation (I use it everywere), hovering over the type actually does expose a fair bit of complexity:

type Animal<T extends TypeNames<{ 
cat: VariantCreator<"cat", (input: { name: string; furnitureDamaged: number; }) => { name: string; furnitureDamaged: number; }, "type">; 
dog: VariantCreator<"dog", (input: { name: string; favoriteBall?: string | undefined; }) => { name: string; favoriteBall?: string | undefined; }, "type">; 
snake: VariantCreator<...>; }> = undefined> = T extends undefined ? {
    type: "cat";
    name: string;
    furnitureDamaged: number;
} | {} /** (.... plus many more lines) */

Meanwhile the early example of using just VariantOf<typeof Animal> looks like the union that you would expect:

type Animal = {
    type: "cat";
    name: string;
    furnitureDamaged: number;
} | {
    type: "dog";
    name: string;
    favoriteBall?: string | undefined;
} | {
    type: "snake";
    name: string;
    pattern: any;
}

As I'm looking at the docs, it seems the main reason for the complicated type is to enable the type Animal<'dog'>

Suggestion

Make a small helper wrapper around Extract to that simplifies getting variations

type Variation<V extends { type: string }, T extends V["type"]> =
    Extract<V, { type: T }>

Usage:

export type Animal = VariantOf<typeof Animal>
const bark = (dog: Variation<Animal, 'dog'>) => {}

export type Snake = Variation<Animal, 'snake'>

Playground Link

  1. API is very simplified and the type definition looks standard
  2. It still autocompletes for the tag ('dog')
  3. Get an error if the tag does not exist in the variant
  4. (opinion) As a consumer it'd be better to reference a type of Dog instead of Animal<'dog'>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions