wonderful-panda/vue-tsx-support

I would like to share some pure function component type definitions with others

GavinRay97 opened this issue · 1 comments

I am not the best at Typescript, so this type may be off a little, but I noticed that when trying to make pure function components two things happened:

  1. The props gave a type error
  2. The TSX element autocomplete does not work correctly -- it does not realize that attributes on the TSX element are actually values to the props object

image

So with this typing, it allows you to pass an interface or a type as a parameter for props, and it will strongly type them in the arguments and on the TSX element for you:

import { RenderContext } from 'vue'
type Maybe<T> = T | undefined | null

type TsxComponent<Props> = (
  args: Partial<RenderContext<Props>> & {
    [k in keyof Props]: Maybe<Props[k]>
  }
) => VueTsxSupport.JSX.Element
interface LabelInputProps {
  name: string
  type: string
}

const LabeledInput: TsxComponent<LabelInputProps> = ({props}) => {
  return (
    <div>
      <p>{props.name}</p>
      <input type={props.type} />
    </div>
  )
}

tsx-types

A warning about this though:

This works through a hack, by copying the properties of the type you pass into TsxComponent<Props> into the argument definitions at the TOP LEVEL. Because the TSX Element seems to autocomplete the parameters as all top-level arguments instead of just props.

RenderContext<Props> adds the types to the { props } definitions, and then [k in keyof Props]: Maybe<T[Props]> adds them to the top-level as well so that they appear as autocomplete options in the TSX Element.

This makes them incorrectly appear as argument values outside of props when destructuring in the function parameters too.

tsx-types-2

If anyone knows how to make this type so that it shows up on the TSX element autocomplete but not in the top-level function params, please post ideas. I think this may not be possible since they have to share a single type definition.

I had a similar problem, but with attrs instead of props. I wanted to create a render helper function for tests that would accept a component and its attrs as arguments, and be type-safe. Didn't solve it, unfortunately.