vue-types
vue-types copied to clipboard
`oneOfType` and `oneOf` support generics
Using generics can help us better constraint types, likes:
type Genre = 'action' | 'thriller'
interface User {
name: string
}
props: {
genre: oneOf<Genre>(['action', 'thriller'])
user: oneOfType<string | User>([String, object()])
}
If you agree, I can provide a PR.
see: https://github.com/IduxFE/idux/blob/main/packages/cdk/utils/src/props.ts#L118
Hi @danranVm, some work to implement type generics is undergoing in https://github.com/dwightjack/vue-types/pull/136 and other PRs referenced there. The latest changes have been published in [email protected].
If you need a fix for oneOfType right away staying on the stable version, you can already achieve the result in your example in a less elegant way:
user: oneOfType([String, object<User>()])
For oneOf I don't plan to add generics at the moment because you can more easily do the same by using a const assertion:
genre: oneOf(['action', 'thriller'] as const)
user: oneOfType([String, object<User>()]) genre: oneOf(['action', 'thriller'] as const)
Hi @dwightjack , thanks for your answer, I know both of these schemes. They work well in most cases, but there are some things that are not friendly. E.g:
// If the non-displayed declaration is null, the type of footer cannot be deduced correctly
footer: oneOfType<any[] | VNode | null>([array(), vNode])
// spelling errors 😭, of course, this is not a problem with `vue-types`, but I want to avoid this problem as much as possible.
genre: oneOf(['action', 'thriler'] as const)
@danranVm [email protected] already supports type arguments for the oneOfType validator. You can try it out right away. As a side note, I'd avoid using null as a prop type in Vue because the framework doesn't really support nullable props even if they might work after all.
As for oneOf, I am not an expert in generics, but I'd like to understand the changes required to make it work.
I have created a branch named ts-args-for-oneof with experimental support: https://github.com/dwightjack/vue-types/compare/ts-args-for-natives...ts-args-for-oneof?expand=1
As you can see from the examples, I created the following scenarios:
// 1
export const oneOfTuple = oneOf<1 | 2 | 'string'>([1, 'string'] as const).def(2)
// 2
export const oneOfTuple2 = oneOf<1 | 2 | 'string'>([1, 2, 'string']).def(1)
// 3
export const oneOfTuple3 = oneOf([1, 2, 'string'] as const).def(1)
I couldn't fix scenario 1, where there should be an error because the array does not include 2 as defined in the union type.
Any idea?
(also tagging @victorgarciaesgi because this discussion is related to https://github.com/dwightjack/vue-types/issues/140)
I will look into this when I have time @dwightjack no problem! 😄
@victorgarciaesgi thanks for your support. for now, I was asking your opinion on the feature, since we are working on these kind of features as well. I don't want you to feel pressed to work on it.
After some research, I am not sure that there's a way to fix the issue in https://github.com/dwightjack/vue-types/issues/147#issuecomment-886476610 (I guess that's the nature of the union type, it cannot force the presence of a value).
For now, I have created a Draft PR with the related changes (https://github.com/dwightjack/vue-types/pull/151). I am not yet fully positive about it: while it helps with typos in the validation array, it allows scenarios with runtime errors not detected by the type checker like:
oneOf<1 | 2 | 'string'>([1, 'string'] as const).def(2) // <-- at runtime this fails
Support for union types in oneOf has been added in version 5 and is now available in [email protected].
Reference:
- https://github.com/dwightjack/vue-types/pull/286