TypeScript types: oneOf() should narrow/constrain the type
See original GitHub issueDescribe the bug
oneOf(..)
constraint should constrain the type to the narrowed values, but it doesn’t.
To Reproduce I couldn’t make a repro with the codesandbox template because this is a TS-specific issue. However this snippet illustrates the issue:
// Works, but overlayed broad type.
const unconstrained: Yup.SchemaOf<string> = Yup.string()
.required()
.oneOf(["foo", "bar"]);
// COMPILER ERROR OUTPUT:
// Type 'RequiredStringSchema<string | undefined, Record<string, any>>' is not assignable to type 'BaseSchema<Maybe<"foo">, Record<string, any>, "foo"> | BaseSchema<Maybe<"bar">, Record<string, any>, "bar">'.
// Type 'RequiredStringSchema<string | undefined, Record<string, any>>' is not assignable to type 'BaseSchema<Maybe<"bar">, Record<string, any>, "bar">'.
// Types of property '__inputType' are incompatible.
// Type 'string | undefined' is not assignable to type 'Maybe<"bar">'.
// Type 'string' is not assignable to type 'Maybe<"bar">'.
const broken: Yup.SchemaOf<"foo" | "bar"> = Yup.string()
.required()
.oneOf(["foo", "bar"]);
Expected behavior
Calling oneOf()
should constrain the schema’s type so that the broken
value (see example above) compiles. I’m also open to other ways of accomplishing this if I’m just “doing it wrong”.
The source (for master at the time of this issue) is part of BaseSchema
:
https://github.com/jquense/yup/blob/67c96ae7f8fcb59758732b2956ff0b7390f08213/src/schema.ts#L668-L697
…However, I don’t think there’s a way to constrain it on BaseSchema
since it uses the polymorphic this
return type, is there? I think you could override the method in StringSchema
, etc to specify a stricter return type… kind of awkward, but it would be an improvement. Let me know your thoughts about a solution - I can make a PR implementing it if you’d like. I’ve made a few for you in the past so you know I’m good for it.
Platform (please complete the following information): Current version of Yup (0.32.8). Problem is also present in master as of now (https://github.com/jquense/yup/tree/67c96ae7f8fcb59758732b2956ff0b7390f08213).
Additional context
Issue #1165 looks to be related, but there isn’t any mention of as const
in the readme anymore so I’m guessing it’s out of date/not relevant anymore.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:15 (4 by maintainers)
@ejose19 You should be able to do it with
mixed<Type>()
. Using it like.mixed<Enum>().oneOf(Object.values(Enum))
worked great for me so farSimilar to what @janKozie1 wrote, you can simply write this as
The cool thing about it is that, if you were to add an option (
baz
) to theoneOf
array, typescript would complain automatically: