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

Vite TypeScript error when building #191

Closed
mirabledictu opened this issue Jul 24, 2021 · 8 comments · Fixed by #193
Closed

Vite TypeScript error when building #191

mirabledictu opened this issue Jul 24, 2021 · 8 comments · Fixed by #193
Labels
bug Something isn't working

Comments

@mirabledictu
Copy link

mirabledictu commented Jul 24, 2021

I have a Vite + Vue project which works fine on development, but when I try to build it, I get this error:

$ vue-tsc --noEmit && vite build
../../node_modules/vue-tsc/typescript/lib/lib.dom.d.ts:11438:87 - error TS2344: Type 'HTMLElementTagNameMap[K]' does not satisfy the constraint 'Node'.
  Type 'HTMLElement | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | HTMLAnchorElement | ... 67 more ... | Picker' is not assignable to type 'Node'.
    Type 'Picker' is not assignable to type 'Node'.
      Types of property 'addEventListener' are incompatible.
        Type '<K extends keyof EmojiPickerEventMap>(type: K, listener: (this: Picker, ev: EmojiPickerEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined) => void' is not assignable to type '(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions | undefined) => void'.
          Types of parameters 'listener' and 'listener' are incompatible.
            Type 'EventListenerOrEventListenerObject | null' is not assignable to type '(this: Picker, ev: EmojiClickEvent | SkinToneChangeEvent) => any'.
              Type 'null' is not assignable to type '(this: Picker, ev: EmojiClickEvent | SkinToneChangeEvent) => any'.

11438     querySelectorAll<K extends keyof HTMLElementTagNameMap>(selectors: K): NodeListOf<HTMLElementTagNameMap[K]>;

The solution for now is to set skipLibCheck to true but I'm worried all other declaration files will get skipped.

{
  "compilerOptions": {
    ...
    "skipLibCheck": true
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

I'm using the API btw.

import Picker from 'emoji-picker-element/picker'
...
data: () => ({
    picker: new Picker()
}),
mounted() {
    const root = this.$refs.root as HTMLDivElement
    root.appendChild(this.picker) // I also get type error here as it is expecting of type DOM
},
...
@nolanlawson
Copy link
Owner

Do you have a sample project that can demonstrate the issue? Which TypeScript version are you using? What is your tsconfig.json?

I tried a basic example using the latest TypeScript and was not able to reproduce.

@nolanlawson nolanlawson added the bug Something isn't working label Jul 24, 2021
@mirabledictu
Copy link
Author

Hi, it's a fresh vite + vue-ts app. Here's my configs

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "skipLibCheck": false
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

package.json

"devDependencies": {
  "@vitejs/plugin-vue": "^1.2.5",
  "@vue/compiler-sfc": "^3.0.5",
  "typescript": "^4.3.2",
  "vite": "^2.4.3",
  "vue-tsc": "^0.0.24"
},

@nolanlawson
Copy link
Owner

Thanks, I found a repro. Here it is: https://github.com/nolanlawson/repro-typescript-vue-issue

Unfortunately I'm not much of a TypeScript expert, and I don't understand why it fails in a vue-ts project but not a vanilla TypeScript project. TypeScript is complaining about:

src/App.vue:19:22 - error TS2345: Argument of type 'Picker' is not assignable to parameter of type 'Node'.

19     root.appendChild(new Picker()) // I also get type error here as it is expecting of type DOM
                        ~~~~~~~~~~~~

node_modules/vue-tsc/typescript/lib/lib.dom.d.ts:11438:87 - error TS2344: Type 'HTMLElementTagNameMap[K]' does not satisfy the constraint 'Node'.
  Type 'HTMLElement | HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | HTMLAnchorElement | ... 67 more ... | Picker' is not assignable to type 'Node'.
    Type 'Picker' is not assignable to type 'Node'.
      Types of property 'addEventListener' are incompatible.
        Type '<K extends keyof EmojiPickerEventMap>(type: K, listener: (this: Picker, ev: EmojiPickerEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined) => void' is not assignable to type '(type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions | undefined) => void'.
          Types of parameters 'listener' and 'listener' are incompatible.
            Type 'EventListenerOrEventListenerObject | null' is not assignable to type '(this: Picker, ev: EmojiClickEvent | SkinToneChangeEvent) => any'.
              Type 'null' is not assignable to type '(this: Picker, ev: EmojiClickEvent | SkinToneChangeEvent) => any'.

11438     querySelectorAll<K extends keyof HTMLElementTagNameMap>(selectors: K): NodeListOf<HTMLElementTagNameMap[K]>;
                                                                                            ~~~~~~~~~~~~~~~~~~~~~~~~

The definition causing the problem is addEventListener here:

addEventListener<K extends keyof EmojiPickerEventMap>(type: K, listener: (this: Picker, ev: EmojiPickerEventMap[K]) => any, options?: boolean | AddEventListenerOptions) {
super.addEventListener(type, listener, options);
}

I borrowed this from some blog post about how to expose custom element TypeScript types, probably this one.

I could just remove the addEventListener and removeEventListener types, but then folks wouldn't get nice typings when they do something like picker.addEventListener('emoji-click').

Can you try some other custom element projects that fire events and see if they work in vue-ts? Maybe this will give me hints about how I can make it work.

@nolanlawson
Copy link
Owner

It looks like if you set strict to false in tsconfig.json then it compiles with no errors.

@janriemer
Copy link

@nolanlawson The actual error is here:
Type 'null' is not assignable to type '(this: Picker, ev: EmojiClickEvent | SkinToneChangeEvent) => any'.

So the definition says it won't accept values that can be null, but the object that is actually passed in can be null.

Try to change the definiton to the following (I haven't actually tried to compile it):

addEventListener<K extends keyof EmojiPickerEventMap>(type: K, listener: ((this: Picker, ev: EmojiPickerEventMap[K])  => any) /*the | null is new here*/ | null, options?: boolean | AddEventListenerOptions) { 
   super.addEventListener(type, listener, options); 
 }

@nolanlawson
Copy link
Owner

Thanks, I tried that, it didn't work. I found another solution though.

@nolanlawson
Copy link
Owner

Fixed in v1.6.5

@mirabledictu
Copy link
Author

Can confirm it's fixed in 1.6.5. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants