Vuetify: [Bug Report] No typings for importing "A La Carte" components

Created on 27 Apr 2018  路  39Comments  路  Source: vuetifyjs/vuetify

Versions and Environment

Vuetify: 1.0.17
Vue: 2.5.16
Browsers: Chrome 66.0.3359.117
OS: Windows 10

Steps to reproduce

Run

$ npm install -g vue-cli
$ vue init vuetifyjs/a-la-carte my-project
$ cd my-project
$ npm install
$ npm run dev

Then you add typescript support to my-project (change main.js to main.ts etc...) by following the official vue page on typescript or something like https://github.com/Microsoft/TypeScript-Vue-Starter

Attempting to run this (i.e. npm run dev) will result in errors such as:

      TS2305: Module '"...../node_modules/vuetify/index"' has no exported member 'VBtn'.

which pertaining to the following import lines in main.ts

import {
  Vuetify,
  VApp,
  VNavigationDrawer,
  VFooter,
  VList,
  VBtn,
  VIcon,
  VGrid,
  VToolbar,
  transitions
} from 'vuetify'

Expected Behavior

no errors. should build and run fine.

Actual Behavior

has errors doesn't build or run

Reproduction Link

https://github.com/vuetifyjs/vuetify/blob/dev/index.d.ts

Other comments

Please update https://github.com/vuetifyjs/vuetify/blob/dev/index.d.ts
You will see over there, that there are actually no references to exported A La Carte components etc..

Note that Even though this pertains to A La Carte, it must actually be fixed in the main vuetify repo is why this issue has been opened here.

enhancement

Most helpful comment

Solved the issue by adding vuetify to tsconfig compiler types

{
    "compilerOptions": {
                ...
        "types": ["node", "jest", "vuetify"],
                ...
}

All 39 comments

image

I've added some basic types: https://github.com/vuetifyjs/vuetify/blob/10c86d1c855af9031fde65f3532e1897c71dc9e8/types/alacarte.d.ts#L1-L15

Unfortunately I couldn't get transform-imports or ts-import-plugin working, so you'll have to import everything like so:

import Vuetify from 'vuetify/es5/components/Vuetify'
import VApp from 'vuetify/es5/components/VApp'
import VNavigationDrawer from 'vuetify/es5/components/VNavigationDrawer'
import VFooter from 'vuetify/es5/components/VFooter'
import VList from 'vuetify/es5/components/VList'
import VBtn from 'vuetify/es5/components/VBtn'
import VIcon from 'vuetify/es5/components/VIcon'
import VGrid from 'vuetify/es5/components/VGrid'
import VToolbar from 'vuetify/es5/components/VToolbar'
import transitions from 'vuetify/es5/components/transitions'
import 'vuetify/src/stylus/app.styl'

will you consider creating a new issue to for the transform-imports / ts-import-plugin aspect.
we want to be able to use this with typescript as closely as one would use it with regular js.. there should be no disadvantages to using this lib with ts.. only advantages :-)

I don't know if there's any more I can do to help with that, if it works I imagine it'd use these types. I spent a couple hours on it but couldn't get anything to happen, but you're welcome to have a go.

Hello! How do you guys found that Typescript accepts a glob pattern for module name?
Just can`t find it in Typescript specs
declare module 'vuetify/es5/components/*'

sorry for off topic! :grin:

Hey,

I tried the above steps and am getting the following:

[ts] Could not find a declaration file for module 'vuetify/es5/components/transitions'. '.../node_modules/vuetify/es5/components/transitions/index.js' implicitly has an 'any' type.
  Try `npm install @types/vuetify` if it exists or add a new declaration (.d.ts) file containing `declare module 'vuetify';`

"dependencies": {
"@types/nprogress": "0.0.29",
"firebase": "^5.3.0",
"nprogress": "^0.2.0",
"register-service-worker": "^1.0.0",
"spinkit": "^1.2.5",
"vee-validate": "^2.1.0-beta.7",
"vue": "^2.5.16",
"vue-class-component": "^6.0.0",
"vue-property-decorator": "^7.0.0",
"vue-router": "^3.0.1",
"vuetify": "^1.2.0-beta.0",
"vuex": "^3.0.1",
"vuex-class": "^0.3.1"
},
"devDependencies": {
"@babel/polyfill": "^7.0.0-beta.55",
"@types/jest": "^23.3.1",
"@vue/cli-plugin-babel": "^3.0.0-rc.10",
"@vue/cli-plugin-e2e-cypress": "^3.0.0-rc.10",
"@vue/cli-plugin-eslint": "^3.0.0-rc.10",
"@vue/cli-plugin-pwa": "^3.0.0-rc.10",
"@vue/cli-plugin-typescript": "^3.0.0-rc.10",
"@vue/cli-plugin-unit-jest": "^3.0.0-rc.10",
"@vue/cli-service": "^3.0.0-rc.10",
"@vue/eslint-config-standard": "^3.0.0-rc.10",
"@vue/eslint-config-typescript": "^3.0.0-rc.10",
"@vue/test-utils": "^1.0.0-beta.23",
"babel-core": "7.0.0-bridge.0",
"babel-plugin-transform-imports": "^1.4.1",
"node-sass": "^4.9.0",
"sass-loader": "^7.0.1",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"ts-jest": "^23.0.0",
"typescript": "^3.0.0",
"vue-cli-plugin-vuetify": "^0.1.6",
"vue-template-compiler": "^2.5.16"
}

@iancrowther Did you fix this? I can't seem to get VSCode to find the typings even though it exists here...

@Li357 what exactly are you importing?
And what level of typings do you actually need?

@qm3ster Right now I'm importing VApp and Vuetify a la carte:

import Vuetify from 'vuetify/es5/components/Vuetify';
import VApp from 'vuetify/es5/components/VApp';

And VSCode complains:

Could not find a declaration file for module 'vuetify/es5/components/Vuetify'. '/Users/li357/Desktop/foobar/node_modules/vuetify/es5/components/Vuetify/index.js' implicitly has an 'any' type.

I don't need any actual typings, but why would the errors be there if I'm just importing a la carte?

Hit the same issue.

@Li357 @tohagan what is the content of your node_modules/vuetify/types/alacarte.d.ts ?
The Vuetify specifically should be covered by this:
https://github.com/vuetifyjs/vuetify/blob/8efe8a13bcc149adaf15033291f62990fd8f5edf/types/alacarte.d.ts#L1-L5

Solved the issue by adding vuetify to tsconfig compiler types

{
    "compilerOptions": {
                ...
        "types": ["node", "jest", "vuetify"],
                ...
}

@JeremyWalters I never had to do that.
Perhaps "moduleResolution" isn't set to "node"?

@qm3ster My compilerOptions with "typescript": "^3.0.0"

"compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "strict": true,
        "jsx": "preserve",
        "importHelpers": true,
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "allowSyntheticDefaultImports": true,
        "sourceMap": true,
        "baseUrl": ".",
        "types": ["node", "jest", "vuetify"],
        "paths": {
            "@/*": ["src/*"]
        },
        "lib": ["es2015", "dom", "dom.iterable", "scripthost"]
    },

@KaelWD Is there a good reason types/index.d.ts is exporting as default something that is both a const and a type?

declare const Vuetify: Vuetify
export default Vuetify
export interface Vuetify {
  install: PluginFunction<VuetifyUseOptions>
  version: string
}

Can I just change it to this?

declare const VuetifyPlugin: Vuetify
export default VuetifyPlugin
export interface Vuetify {
  install: PluginFunction<VuetifyUseOptions>
  version: string
}

@qm3ster : node_modules/vuetify/types/alacarte.d.ts

declare module 'vuetify/es5/components/Vuetify' {
  import Vuetify from 'vuetify'

  export default Vuetify
}

// TODO: transitions
declare module 'vuetify/es5/components/*' {
  import { PluginFunction, PluginObject, VueConstructor, ComponentOptions } from 'vue'

  interface PluginConstructor extends VueConstructor {
    install: PluginFunction<never>
  }

  const Component: {
    default: PluginConstructor,
    [key: string]: PluginConstructor
  }

  export = Component
}

declare module 'vuetify/es5/directives' {
  import { PluginFunction } from 'vue'
  import { VuetifyDirective } from 'vuetify'

  const ClickOutside: VuetifyDirective
  const Ripple: VuetifyDirective
  const Resize: VuetifyDirective
  const Scroll: VuetifyDirective
  const Touch: VuetifyDirective

  const Plugin: PluginFunction<never>

  export {
    ClickOutside,
    Ripple,
    Resize,
    Scroll,
    Touch
  }
  export default Plugin
}

@tohagan yeah, that file is supposed to be re-exporting just the const, not the interface.

@Li357 Sorry no, I had to park this!

Is this supposed to be fixed? Just created test project with vue-cli 3 with typescript and still got this problem. All a la carte imports apart first one - vuetify - are erroneous.

You need "types": ["vuetify"] in tsconfig, I haven't got around to fixing it in the cli plugin yet.

@KaelWD adding "types": ["vuetify"] in tsconfig doesn't solve the problem unfortunately.
I am getting similar error.
[ts] 'Vuetify' only refers to a type, but is being used as a value here.

Why do we need typings when the source is already typescript?

adding "types": ["vuetify"] in tsconfig doesn't solve the problem unfortunately.

Same, problem still exists when installing vue via vue-cli and then adding vuetify via vue add vuetify and chosing a-la-carte.
How to resolve that?

I resolved it by making it a.js file instead of.ts until there is a better solution

Yep, installed via vue-cli add vuetify and am getting this error...

same here: Could not find a declaration file for module 'vuetify/lib

I hit a similar issue. However using types is not a solution. I am getting tons of errors. I believe this is because in our project we are using typeRoots.

According to the documentation, those compiler options are exclusive. You can't use both.
For now I use this workaround in my tsconfig.json:

{
    "compilerOptions": {
        //...
    },
    "include": [
        "node_modules/vuetify/types",
    ]
}

Given that TypeScript does not allow to have an array in the package.json types field, the solution would be, as a build step, to merge all the declaration files in the types folder into one.

@KaelWD Would you accept a PR that did the above?

 "include": [
        ..., // let the default includes
        "node_modules/vuetify/types", // add this one
    ]
  "exclude": [
    "node_modules/^(?!vuetify/types).*$" // change the default exclude rule to this
  ],

Just that and it's ok.

@Nemikolh

the solution would be, as a build step, to merge all the declaration files in the types folder into one

I don't really understand how that would help, don't you still need to tell tsc to include that somehow?

@KaelWD Sorry, after re-reading my comment, I realized that it wasn't really clear.

By default, for an imported package named foo, typescript will search for foo in node_modules/ and in node_modules/@types. If found, it tries to load an index.d.ts within the foo package unless a types property is specified in the package.json, in which case it loads that file instead.

Currently, vuetify specify the types property and points typescript to the types/index.d.ts file.

https://github.com/vuetifyjs/vuetify/blob/7e9dab28955215890e5b9182f27e13a1cd618dac/packages/vuetify/package.json#L15

However this files only include a subset of all type definitions of the different way vuetify can be used.

My previous suggestion involved renaming index.d.ts to something like main.d.ts (or whatever you'd like) and have index.d.ts being automatically generated, preferably before publishing so maybe in a prepublish hook. And it would be a concatenation of all files present, so:

  • alacarte.d.ts
  • lib.d.ts
  • colors.d.ts
  • lang.d.ts
  • main.d.ts (currently named index.d.ts)

Does that makes sense?

All of those are imported by index.d.ts, there's no need to concatenate them.

for an imported package named foo

That's the problem here, we're importing vuetify/lib which doesn't have it's own package.json but instead relies on the main vuetify types already being available.

All of those are imported by index.d.ts, there's no need to concatenate them.

I completely missed those lines. I guess this might be a bug in TypeScript, I'll investigate more.

That's the problem here, we're importing vuetify/lib which doesn't have it's own package.json but instead relies on the main vuetify types already being available.

In my understanding (but I'll have to check), TypeScript knows that anything of the form vuetify/some/path will refers to the types defined by the vuetify package as it is how node works. So a package.json in lib wouldn't help.

Ok, I am very confused. I tried to create a simple project that would expose the problem we are facing, but in that small repo, everything just works. I am really starting to think that this might be a weird bug in the TypeScript compiler.
Anyway, thanks for the quick reply @KaelWD. :+1: It's really appreciated.

@pascoual's solution above works for the time being.

"include": [
   "node_modules/vuetify/types",
 ],
"exclude": [
  "node_modules/^(?!vuetify/types).*$"
],

Unfortunately, this is still an issue, and quite annoying for newcomers to Vue/Vuetify/TypeScript: "ERROR in C:/Users/nemet/tiva11/tiva11forvue/src/plugins/vuetify.ts
2:21 Could not find a declaration file for module 'vuetify/lib'. .../node_modules/vuetify/lib/index.js' implicitly has an 'any' type. Try npm install @types/vuetify if it exists or add a new declaration (.d.ts) file containing declare module 'vuetify/lib';

Fortunately, @pascoual solution worked to me, either.

The problem still exists when trying to import individual components in unit tests.

 /projects/myApp/GUI/node_modules/vuetify/lib/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Vuetify from './components/Vuetify';
                                                                                                    ^^^^^^^

    SyntaxError: Unexpected identifier

      11 | import DefaultMenu from '@/components/default-menu.vue';
      12 | import { MainMenu, TMenuState } from '@/vuex/main-menu.ts';
    > 13 | import {VList} from 'vuetify/lib';

I added vuetify with the CLI and got the typescript error. This solution worked for me:
https://github.com/vuetifyjs/vuetify/issues/3943#issuecomment-414551981

TLDR: In tsconfig.json add vuetify to the list of types

I added vuetify with the CLI and got the typescript error. This solution worked for me:
#3943 (comment)

TLDR: In tsconfig.json add vuetify to the list of types

I think this should be added into the document of https://vuetifyjs.com/en/framework/a-la-carte

this problem still exists in Vuetify 2, even after adding "vuetify" to types (in tsconfig.json)

Is it possible to add more specific typings for individual components?

For example, adding method definitions like "reset()" or 'validate()" on Input Components?

This will immensely increase productivity for TypeScript users!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

milleraa picture milleraa  路  3Comments

Antway picture Antway  路  3Comments

chriswa picture chriswa  路  3Comments

cawa-93 picture cawa-93  路  3Comments

itanka9 picture itanka9  路  3Comments