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

oneOfType and oneOf support generics #147

Closed
danranVm opened this issue Jul 22, 2021 · 8 comments
Closed

oneOfType and oneOf support generics #147

danranVm opened this issue Jul 22, 2021 · 8 comments
Assignees
Labels

Comments

@danranVm
Copy link

danranVm commented Jul 22, 2021

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()])
}
@danranVm
Copy link
Author

danranVm commented Jul 22, 2021

If you agree, I can provide a PR.

see: https://github.com/IduxFE/idux/blob/main/packages/cdk/utils/src/props.ts#L118

@dwightjack
Copy link
Owner

Hi @danranVm, some work to implement type generics is undergoing in #136 and other PRs referenced there. The latest changes have been published in vue-types@4.1.0-beta.2.

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)

@dwightjack dwightjack self-assigned this Jul 22, 2021
@danranVm
Copy link
Author

danranVm commented Jul 23, 2021

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)

@dwightjack
Copy link
Owner

@danranVm vue-types@4.1.0-beta.2 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 #140)

@victorgarciaesgi
Copy link
Collaborator

I will look into this when I have time @dwightjack no problem! 😄

@dwightjack
Copy link
Owner

@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.

@dwightjack
Copy link
Owner

After some research, I am not sure that there's a way to fix the issue in #147 (comment) (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 (#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

@dwightjack dwightjack modified the milestone: 4.1.0 Jul 29, 2021
@dwightjack
Copy link
Owner

Support for union types in oneOf has been added in version 5 and is now available in vue-types@5.0.0-rc.1.

Reference:

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

No branches or pull requests

3 participants