Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue + typescript - TypeError: Object prototype may only be an Object or null: undefined

TypeError: Object prototype may only be an Object or null: undefined

I got some error in my project. I'm using vuejs, typescript and jest.

It's just simple code and I tried to unit test with jest, but It have some error. Here is my test code.

///<reference path="../../../../node_modules/@types/jest/index.d.ts"/>
// https://vue-test-utils.vuejs.org/kr/s
import { mount } from "vue-test-utils";
import HelloWorld from './HelloWorld.vue';

describe('[HelloWorld]', function () {
  let cmp: any;

  beforeEach(() => {
    cmp = mount(HelloWorld);
  });

  it("Check vue instance", () => {
    expect(cmp.isVueInstance()).toBeTruthy();
  });

  it("message is Hello", () => {
    expect(cmp.vm.msg).toEqual('Hello!!');
  });
});

and Here is vue file

   <template>
   <div class="hello">
       <h1>{{ msg }}</h1>
       <img src="/assets/logo.png">
       <button @click="clickHandler">
         button
       </button>
     </div>
   </template>

   <script lang="ts">
   import Vue from "vue";
   import Component from "vue-class-component";

   interface HelloWorldInterface {
     msg: string;
     clickHandler(): void;
   }

   @Component({})
   export default class HelloWorld extends Vue implements HelloWorldInterface {
     msg = "Hello!!";
     clickHandler() {
       window.alert(this.msg);
     }
   }
   </script>

Here is error logs with picture.

like image 824
Younghoon Kim Avatar asked Feb 26 '18 15:02

Younghoon Kim


3 Answers

You should set esModuleInterop = true for your tsconfig.json or your own tsconfig just for jest

like image 74
Hoang Vu Avatar answered Sep 25 '22 14:09

Hoang Vu


The problem seems to be how Vue2 exposes itself, so import Vue from "vue" causes this error.

I fixed it by using 'vue-property-decorator' like this:

import { Vue, Component, Prop } from 'vue-property-decorator';

So what does 'vue-property-decorator' do? It imports and then exports Vue not as default but named export. I guess you could do that in your own code, if you wanted.

import Vue, { PropOptions, WatchOptions } from 'vue';
...
export { Component, Vue, mixins as Mixins };
like image 39
Reynicke Avatar answered Sep 25 '22 14:09

Reynicke


For me, using import * as Vue from "vue" instead of import Vue from "vue" fixed the problem for my projects with a similar setup, i.e.:

//import Vue from "vue";
import * as Vue from "vue";
import Component from "vue-class-component";

interface HelloWorldInterface {
  msg: string;
  clickHandler(): void;
}

@Component
export default class HelloWorld extends Vue implements HelloWorldInterface {
  msg = "Hello!!";
  clickHandler() {
    window.alert(this.msg);
  }
}

It is a lot more cumbersome, but at least it works. I have setup a proof-of-concept example using vue-cli: https://codesandbox.io/s/mjvjw2xw39

like image 36
Terry Avatar answered Sep 23 '22 14:09

Terry