Skip to content

Create a union from readonly array #361

Open
@cjcartier

Description

@cjcartier

Is there an existing issue for this?

  • I have searched the existing issues

Code of Conduct

  • I agree to follow this project's Code of Conduct

Question

I used to have a decent function for this in V0. But with V1 I get a TS error that slows down my entire project. Simply I want to do something like:

const array = ['a', 'b', 'c'] as const;

const fragment = q.fragment<any>().project({
   prop: constructUnionFromArray(array),
});

type FragmentResult = InferFragmentType<typeof fragment>;
{
   prop: 'a' | 'b' | 'c';
}

I was using this heavily as sometimes I might have pretty long lists of literals that would be cumbersome to update (like icon IDs, colors, etc). So I added a the function below in order to generate the lists and it was working great:

import { z } from 'zod';

import { q } from 'lib/client';

export const isValidZodLiteralUnion = <T extends z.ZodLiteral<unknown>>(literals: T[]): literals is [T, T, ...T[]] =>
  literals.length >= 2;

export const constructZodLiteralUnionType = <T extends z.ZodLiteral<unknown>>(literals: T[]) => {
  const uniqueLiterals = [...new Set(literals)];

  if (!isValidZodLiteralUnion(uniqueLiterals)) {
    throw new Error(
      'Literals passed do not meet the criteria for constructing a union schema, the minimum length is 2',
    );
  }

  return q.union(uniqueLiterals);
};

export const constructLiteralArray = <T extends string>(literals: T[]): z.ZodLiteral<T>[] =>
  literals.map(literal => z.literal(literal));

export const constructUnionFromArray = <T extends string>(literals: T[]) =>
  constructZodLiteralUnionType(constructLiteralArray(literals));

NOTE: There are updates below so that it works with the new V1.

Not the issue is with return q.union(uniqueLiterals). I get the error Type instantiation is excessively deep and possibly infinite. And that slows the project to a crawl. I have been trying to update this to get it to work again but figured I would shoot you all a message to see if you have a solution that you prefer.

Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    groqd-v1Related to the newer `v1.x` packageneeds-more-infoNeeds more information

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions