wonderful-panda/vue-tsx-support

[Bug] Object literal may only specify known properties, and 'data' does not exist in type 'FunctionalComponentOptions<unknown, RecordPropsDefinition<unknown>>'.

gd4Ark opened this issue · 11 comments

Example

import * as tsx from "vue-tsx-support";
const MyComponent = tsx.componentFactory.create({
+  data() {
+   return {
+      a: 1,
+   }
+  },
  props: {
    text: { type: String, required: true },
    important: Boolean,
  } as const, // `as const` is needed in some cases.
  computed: {
    className(): string {
      return this.important ? "label-important" : "label-normal";
    }
  },
  methods: {
    onClick(event) { this.$emit("ok", event); }
  },
  render(): VNode {
    return <span class={this.className} onClick={this.onClick}>{this.text}</span>;
  }
});

Error

TS2769: No overload matches this call. friendly-errors 16:40:09
Overload 1 of 2, '(options: FunctionalComponentOptions<unknown, RecordPropsDefinition>, requiredProps?: never[] | undefined): _TsxComponentV3<Vue & { ...; }, ... 4 more ..., {}>', gave the following error.
Argument of type '{ name: string; props: { value: { type: () => Status; required: boolean; }; readonly: { type: BooleanConstructor; default: boolean; }; }; data(this: CombinedVueInstance<Vue & { _tsx: TsxComponentTypeInfo<{}, {}, Events, {}>; $scopedSlots: InnerScopedSlots<...>; } & { ...; }, unknown, unknown, unknown, Readonly<...>>...' is not assignable to parameter of type 'FunctionalComponentOptions<unknown, RecordPropsDefinition>'.
Object literal may only specify known properties, and 'data' does not exist in type 'FunctionalComponentOptions<unknown, RecordPropsDefinition>'.
Overload 2 of 2, '(options: object & ComponentOptions<Vue & { _tsx: TsxComponentTypeInfo<{}, {}, Events, {}>; $scopedSlots: InnerScopedSlots<{}>; } & { _tsx: DeclareProps<{ ...; } & { ...; }>; }, ... 4 more ..., { ...; }> & ThisType<...> & { ...; }, requiredPropsNames?: ("value" | "readonly")[] | undefined): _TsxComponentV3<...>', gave the following error.
Property '_tsx' is missing in type '{ value: { type: () => Status; required: true; }; readonly: { type: BooleanConstructor; default: false; }; }' but required in type 'RecordPropsDefinition<{ value: Status; readonly: boolean; _tsx: DeclareProps<{ value: Status; } & { readonly?: boolean | undefined; }>; }>'.
37 | }

Information

Temporarily work

import * as tsx from "vue-tsx-support";
const MyComponent = tsx.componentFactory.create({
-  data() {
-   return {
-      a: 1,
-   }
-  },
+  data: () => ({
+   a: 1,
+  }),
  props: {
    text: { type: String, required: true },
    important: Boolean,
  } as const, // `as const` is needed in some cases.
  computed: {
    className(): string {
      return this.important ? "label-important" : "label-normal";
    }
  },
  methods: {
    onClick(event) { this.$emit("ok", event); }
  },
  render(): VNode {
    return <span class={this.className} onClick={this.onClick}>{this.text}</span>;
  }
});

Version

Work:<= v3.0.0-dev.6e
Not Work:>= v3.0.0-dev.6e

It works for me (v3.0.2).

Try v3.0.2, and show me these information if the problem still exists.

  • Vue version
  • TypeScript version
  • tsconfig.json content

@wonderful-panda
version:

  • vue-tsx-support@3.0.2
  • typescript@4.0.5
  • vue@2.6.12
  • nuxt@2.11.0
  • @nuxt/typescript-build@2.0.3

tsconfig:

{
  "compilerOptions": {
    "target": "es2018",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": ["esnext", "esnext.asynciterable", "dom"],
    "esModuleInterop": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": true,
    "experimentalDecorators": true,
    "baseUrl": ".",
    "jsx": "preserve",
    "jsxFactory": "VueTsxSupport",
    "paths": {
      "~/*": ["./src/*"],
      "@/*": ["./src/*"]
    },
    "types": ["@types/node", "@nuxt/types", "@nuxtjs/axios"],
    "skipLibCheck": true
  },
  "exclude": ["node_modules", ".nuxt", "dist"]
}

Still works for me.
Can you provide minimal reproduction repository ?

@wonderful-panda
The reproduction example is placed here, mainly in this file

Best regards.

Try this.

+import { VNode } from "vue";
import * as tsx from "vue-tsx-support";
const MyComponent = tsx.componentFactory.create({
  data() {
   return {
      a: 1,
   }
  },
  props: {
    text: { type: String, required: true },
    important: Boolean,
  } as const, // `as const` is needed in some cases.
  computed: {
    className(): string {
      return this.important ? "label-important" : "label-normal";
    }
  },
  methods: {
    onClick(event) { this.$emit("ok", event); }
  },
  render(): VNode {
    return <span class={this.className} onClick={this.onClick}>{this.text}</span>;
  }
});

@wonderful-panda
It's working, thank you very much!

PS: But perhaps this description should be added to the readme.md example?

@wonderful-panda Another problem found is that if I define the parameters of the handler of watch with a type other than any, I get the same error.

It's not working:

  watch: {
    a(v: number) {
      console.log(v)
    },
  },

It's working:

  watch: {
    // a(v:any) {
    a(v) {
      console.log(v)
    },
  },

I don't know if it has something to do with type declarations in vuejs, see: https://github.com/vuejs/vue/blob/dev/types/options.d.ts#L79

I'm not sure if this question is from vue-tsx-support,but if I use Vue.extend() instead of tsx.componentFactory.create(), it won't have this error!

fixed.
I'll release patched version in this weekend.

fixed in 3.0.3

@wonderful-panda for me this issue still exists on vue-tsx-support v3.2.0

@wonderful-panda So I spent about 8 hours yesterday first figuring out what exactly the issue was, and when I found it was the watchers argument typing that was the cause, I went ahead and forked the library, I tried to reproduce my issue based on this test:

https://github.com/wonderful-panda/vue-tsx-support/blob/master/test/tsc/basic/componentFactory.tsx#L54~L71

But after trying about 3 hours all sort of things, I can't seem to reproduce it.... ><

My current work around is to not define the argument types in my watchers, and only do it inside the function scope of the watcher. Not ideal, but it works for now.