What does the shims-tsx.d.ts file do in a Vue-Typescript project?
Asked Answered
A

3

89

When creating a Vue project with typescript, two declaration files are included: shims-vue.d.ts and shims.tsx.d.ts.

//shims-vue.d.ts

declare module "*.vue" {
  import Vue from 'vue';
  export default Vue;
}

And:

//shims-tsx.d.ts

import Vue, { VNode } from 'vue';

declare global {
  namespace JSX {
    // tslint:disable no-empty-interface
    interface Element extends VNode {}
    // tslint:disable no-empty-interface
    interface ElementClass extends Vue {}
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}

While creating a small project (without the Vue CLI) I forgot to include the second (shims.tsx.d.ts) and my project compiles and runs as expected (without error).

I found this post about it: https://github.com/vuejs/vue-cli/issues/1198, but was hoping for more clarification.

I am just curious what this file does and why it is included? In other words, what I would have to do to "break" my app if I don't include this declaration file.

Thanks!

Archery answered 11/2, 2019 at 0:40 Comment(0)
B
57

The first file helps your IDE to understand what a file ending in .vue is

The second file allows you to use .tsx files while enabling jsx syntax support in your IDE to write JSX-style typescript code.

Busty answered 11/2, 2019 at 1:45 Comment(2)
could you please elaborate the first part a bit? I've tried commenting out the whole file and don't see any difference really (build is successful as well)Kristoferkristoffer
I am finding that an error where a module is not found using an index.ts page to prevent circular dependencies is fixed when the first bit (shims-vue.d.ts) is includedPisci
F
91

This link was the only decent explanation I could find. Basically it has to do with Webpack.

If you aren't using Webpack - you're only using Typescript, then doing something like this is an error:

import Foo from "./Foo.vue";

Because obviously Typescript doesn't understand .vue files - they aren't actually Typescript modules.

However, if you set up a Vue project you'll find that it does it all the time. How does that work? Webpack! As far as I can tell (I have tried to avoid insanity by learning anything at all about webpack), this is basically Webpack's job - it goes through all of the import files in your Javascript/Typescript, and "bundles" them, i.e. it merges them into one file.

But it is extensible with "loaders" (terrible name) that can be added to handle particular file formats. For example you can configure it to use a CSS loader. That means when it finds

import "./foo.css"

It will bundle the CSS into the output, and probably add some JavaScript to insert it into the DOM at runtime, or some nonsense like that.

Anyway, there's also (I presume) a loader for *.vue files that handles bundling those. So that's why import Foo from "./Foo.vue" works. Why do we need the shim file?

Because Typescript still isn't happy. It doesn't know anything about Webpack, so it will still throw an error when you try and import Foo.vue (it'll tell you Can't find module "./Foo.vue").

The solution is shims-vue.d.ts. The filename does not seem to be important, as long as it ends with .d.ts. I guess Typescript looks for all .d.ts in the same directory or something like that.

In any case, the contents are this:

declare module "*.vue" {
  import Vue from 'vue';
  export default Vue;
}

Which basically means, "every time you import a module with the name *.vue (wildcards are supported), then don't actually do it - instead treat it as if it had these contents".

This is how it seems to behave for me: If you do import Foo from "./Foo.vue" then the type of Foo will by Vue. There does not seem to be a way to actually import the Foo type.

Edit: Actually I think it works *if you import the component in another .vue file. If you import it from .ts then you just get an alias for Vue. This is annoying in tests! I made another question about this.

Flowerless answered 17/1, 2020 at 13:41 Comment(0)
B
57

The first file helps your IDE to understand what a file ending in .vue is

The second file allows you to use .tsx files while enabling jsx syntax support in your IDE to write JSX-style typescript code.

Busty answered 11/2, 2019 at 1:45 Comment(2)
could you please elaborate the first part a bit? I've tried commenting out the whole file and don't see any difference really (build is successful as well)Kristoferkristoffer
I am finding that an error where a module is not found using an index.ts page to prevent circular dependencies is fixed when the first bit (shims-vue.d.ts) is includedPisci
G
1

Typescript must understand what your trying to do, for typescript to do so, your tsconfig.json file(rules) does not cover the shims.d.ts file, you must pass it under the include option for it to know what the shims.d.ts file is

Granadilla answered 28/5, 2023 at 14:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.