Subscribe on changes!

Event handler props' types fail on custom component in `.tsx` file.

avatar
Jan 16th 2021

Version

3.0.5

Reproduction link

https://codesandbox.io/s/gifted-minsky-w5dxn?file=/src/index.tsx

with ts config

{
  "compilerOptions": {
    "strict": true,
    "module": "commonjs",
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",
    "esModuleInterop": true,
    "sourceMap": true,
    "allowJs": true,
    "lib": [
      "es6",
      "dom"
    ],
    "rootDir": "src",
    "moduleResolution": "node"
  }
}

image

Steps to reproduce

Follow the link.

What is expected?

<Comp onClick={() => {}} /> shouldn't have type error.

What is actually happening?

has type error

avatar
Jan 16th 2021

Vue denies unknown props by default, you can change this behavior through ComponentCustomProps:

declare module 'vue' {
  interface ComponentCustomProps {
    custom?: number
  }
}

Check this file: https://github.com/vuejs/vue-next/blob/master/test-dts/componentTypeExtensions.test-d.tsx , you can get more examples.

avatar
Jan 16th 2021

https://github.com/vuejs/vue-next/blob/master/test-dts/componentTypeExtensions.test-d.tsx

I wonder why it works in raw h function but not in tsx. Could you please explain what does the transformation do? Thanks. @HcySunYang

Since inheritAttrs works by default, I think it is wired that DOM events props are not allowed.

avatar
Jan 16th 2021

The reason is for type-safety, see https://github.com/vuejs/vue-next/issues/1519.

I wonder why it works in raw h function but not in tsx. Could you please explain what does the transformation do?

As I currently know, h doesn't deny unknown props by default, which does cause inconsistent behavior, so for this reason I reopen it for subsequent discussion.

avatar
Jan 16th 2021

In my original recognition I thought tsx just do a raw transformation from <div onClick={null} /> to h('div', { onClick: null }) and do the identical type checking. However, currently it works differently in typescript (when building & editing). What's the reason of the behavior?

avatar
Jan 16th 2021

TSX has different type checking rules than h, here is about jsx type checking: https://www.typescriptlang.org/docs/handbook/jsx.html. For h, it's just a function call and has nothing to do with the type checking of jsx

avatar
Jan 16th 2021

Thanks! And I find it's wired to implement v-model in tsx. To make props like onUpdate:value work, I need to write <Comp {...{ 'onUpdate:value': null }} />.

image

I think it make it hard to build a library for both tsx & template usage. Is there any better workaround to solve the problem?

Currently type checking is not at a production level in sfc's template. Which forces people who wants to take advantages of type checking to use tsx.

Is it possible to treat onUpdateXxx as onUpdate:xxx in vue (maybe in later version)? Just like xmlns:xlink in react.

avatar
Jan 16th 2021

You can use https://github.com/vuejs/jsx-next And, I close this issue. If you think the type checking between h and jsx still bothers you (inconsistent behavior), then you can open a new issue about that.