Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v.literal should accept spread arguments #19

Open
Geordi7 opened this issue Oct 20, 2021 · 4 comments
Open

v.literal should accept spread arguments #19

Geordi7 opened this issue Oct 20, 2021 · 4 comments

Comments

@Geordi7
Copy link

Geordi7 commented Oct 20, 2021

Today:

const T = v.union(v.literal('a'), v.literal('b'), v.literal('c'));

Tomorrow:

const T = v.literal('a', 'b', 'c');
@marvinhagemeister
Copy link
Contributor

I can see how it makes the code more concise, but I'm not sure about moving away from the explicitness valita currently offers. I like that currently a literal type is always a literal type and not a magic union + literals.

@Geordi7
Copy link
Author

Geordi7 commented Feb 1, 2023

how about calling it literals ?

import * as v from '@badrap/valita';

const A = v.literals('a', 'b');
// equivalent to
const B = v.union(v.literal('a'), v.literal('b'));

@dimatakoy
Copy link
Contributor

dimatakoy commented Jul 28, 2023

I personally dislike it, current .union is much more generic, than function that can only handle strings. You can easily make own helper for this single case.

const TYPES = {
	first: '__first',
	second: '__second',
} as const;

function fromConst<T extends string>(input: Record<string, T>) {
	const literals = Object.values(input).map((type) => v.literal(type));
	return v.union(...literals);
}

const types = fromConst(TYPES);

type x = v.Infer<typeof types>;
//   ^ '__first' | '__second'

@Geordi7
Copy link
Author

Geordi7 commented Feb 14, 2024

@dimatakoy - your example doesn't really capture my intent.

This is what I add to my projects that use valita:

export const vLiterals = <L extends string | boolean | number>(...literals: L[]) =>
  v.union(...literals.map(l => v.literal(l))) as v.Type<L>

const vOneOrHello = vLiterals(1,'hello');
type OneOrHello = v.Infer<typeof vOneOrHello> // 1 | 'hello'

it works as you'd expect, this is a QOL change for valita, not a whole new type parser, under the hood it's just a union parser of literal parsers, which you would have to write anyway. I'm suggesting that valita includes it because it's simple and useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants