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

type Inference incorrect of DefineComponent with HTMLAttributes #4689

Open
danranVm opened this issue Sep 27, 2021 · 5 comments · May be fixed by #5031
Open

type Inference incorrect of DefineComponent with HTMLAttributes #4689

danranVm opened this issue Sep 27, 2021 · 5 comments · May be fixed by #5031
Assignees
Labels
has workaround A workaround has been found to avoid the problem 🐞 bug Something isn't working scope: types

Comments

@danranVm
Copy link

danranVm commented Sep 27, 2021

Version

3.2.19

Reproduction link

Steps to reproduce

const props = {
  propA: Number,
  propB: [String, Number],
  propC: {
    type: String,
    required: true,
  },
}

const Comp = defineComponent({
  props,
  setup() {
    return <div></div>
  },
}) as unknown as DefineComponent<HTMLAttributes & typeof props>

const render = () => {
  const onClick = () => {}
  return <Comp propA={1} onClick={onClick}></Comp>
}

What is expected?

What is actually happening?

image

Type 'number' is not assignable to type 'NumberConstructor'.

@danranVm
Copy link
Author

The cause of this problem is due to this change: #4578

@danranVm
Copy link
Author

danranVm commented Sep 27, 2021

const Comp = defineComponent({
  props,
  setup() {
    return <div></div>
  },
}) as unknown as DefineComponent<HTMLAttributes & ExtractPropTypes<typeof props>>

Using 'ExtractPropTypes' to wrap props makes it work, is there a better solution?
Then I had a new problem, when I changed 'required' to 'default'

const props = {
  propA: Number,
  propB: [String, Number],
  propC: {
    type: String,
    default: 'true', // required => default
  },
}

const Comp = defineComponent({
  props,
  setup() {
    return <div></div>
  },
}) as unknown as DefineComponent<HTMLAttributes & ExtractPropTypes<typeof props>>

const render = () => {
  const onClick = () => {}
  return <Comp propB={'123'} onClick={onClick}></Comp>
}

image

@yyx990803
Copy link
Member

/cc @Amour1688

@Amour1688
Copy link
Member

This seems to be the bug of ExtractPropTypes.

And there is a better solution if you want to extends your props

const props = {
  propA: Number,
  propB: [String, Number],
  propC: {
    type: String,
    required: true,
  },
}

const Comp = defineComponent<HTMLAttributes & ExtractPropTypes<typeof props>>({
  setup() {
    return <div></div>
  },
})

// for runtime
Comp.props = props

@Amour1688 Amour1688 added the 🐞 bug Something isn't working label Sep 27, 2021
@Amour1688 Amour1688 self-assigned this Sep 27, 2021
@danranVm
Copy link
Author

my final solution is as follows:

export const iconProps = {
  iconfont: IxPropTypes.bool.def(false),
  name: IxPropTypes.string,
  rotate: IxPropTypes.oneOfType([Boolean, Number, String]),
}

export type IconProps = IxInnerPropTypes<typeof iconProps> // This is the type used internally
export type IconPublicProps = IxPublicPropTypes<typeof iconProps> // This is the type of exposure to the user
export type IconComponent = DefineComponent<Omit<HTMLAttributes, keyof IconPublicProps> & IconPublicProps>
export type IconInstance = InstanceType<DefineComponent<IconProps>>

'IxInnerPropTypes' and' IxPublicPropTypes' are defined in https://github.com/IDuxFE/idux/blob/main/packages/cdk/utils/src/props.ts#L54

the type of the icon component is defined in https://github.com/IDuxFE/idux/blob/main/packages/components/icon/src/types.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has workaround A workaround has been found to avoid the problem 🐞 bug Something isn't working scope: types
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants