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

Improve prop types #111

Open
2 of 3 tasks
mesqueeb opened this issue Feb 5, 2022 · 0 comments
Open
2 of 3 tasks

Improve prop types #111

mesqueeb opened this issue Feb 5, 2022 · 0 comments

Comments

@mesqueeb
Copy link
Member

mesqueeb commented Feb 5, 2022

  • BlitzTable
  • BlitzField
  • BlitzForm

@mesqueeb This is possible with a bit of type magic, yes.

import {
  ExtractPropTypes,
 ExtractDefaultPropTypes,
} from 'vue'
import { SetOptional } from 'type-fest'

export type ExternalProps<T extends Record<string | number | symbol, {}>> 
  = SetOptional<ExtractPropTypes<T>, keyof ExtractDefaultPropTypes<T>>

Usage:

import { ExternalProps } from './typeUtils.ts'
import { PropTypes } from 'vue'
// Example custom types
interface User {
  name: string
}
interface Post {
  title: string
}

const mySharedProps = {
  user: {
    type: Object as PropType<User>,
    default: () => ({ name: 'Tom' })
  },
  post: {
    type: Object as PropType<Post>,
    required: true,
  },
} as const // <= THIS IS NECESSARY TO DETECT REQUIRED PROPS CORRECTLY!

export type MySharedProps = ExternalProps<typeof mySharedProps>

//This is the resulting type:
type MySharedProps = {
  user?: User | undefined // has default value internally, but from parent's perspective it's optional
  post: Post // required
}

A little bit on how this works:

ExtractPropTypes gives you almost what you want, but the resulting interface has props with a default value marked as required. This is because this interface is the internal props interface - this.$props, where props with default values are guaranteed to be present.

So we need to make these optional. How?

  • ExtractDefaultPropTypes gives us an interface with only those props that have default values
  • We then use the keys of this interface with keyof ...
  • and make these keys optional on the interface provided by ExtractPropTypes

For the last step I use SetOptional from the amazing type-fest collection of useful types, but I'm sure there's a SO answer out there that explains how to make properties on an interface optional if you don't want to add another dependency.

Also, yes - I think it would make real sense to have this in the core types.

Originally posted by @LinusBorg in vuejs/core#4294 (comment)

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

1 participant