vuematerial / vue-material

Vue.js Framework - ready-to-use Vue components with Material Design, free forever.
https://www.creative-tim.com/vuematerial
MIT License
9.88k stars 1.16k forks source link

[core] Typescript support planned? #662

Open akaSybe opened 7 years ago

akaSybe commented 7 years ago

I started a project and I want to use vue-material with Typescript. As far as I can see there is no Typescript support right now.

CatsMiaow commented 7 years ago

vue-material/index.d.ts

import Vue from 'vue';

type Component = 'MdCore'
  | 'MdAvatar'
  | 'MdBackdrop'
  | 'MdBottomBar'
  | 'MdButton'
  | 'MdButtonToggle'
  | 'MdCard'
  | 'MdCheckbox'
  | 'MdChips'
  | 'MdDialog'
  | 'MdDivider'
  | 'MdFile'
  | 'MdIcon'
  | 'MdImage'
  | 'MdInputContainer'
  | 'MdLayout'
  | 'MdList'
  | 'MdMenu'
  | 'MdProgress'
  | 'MdRadio'
  | 'MdSelect'
  | 'MdSidenav'
  | 'MdSnackbar'
  | 'MdSpeedDial'
  | 'MdSpinner'
  | 'MdSubheader'
  | 'MdSwitch'
  | 'MdTable'
  | 'MdTabs'
  | 'MdToolbar'
  | 'MdTooltip'
  | 'MdWhiteframe';

type Options =
  { install: Vue.PluginFunction<never>} &
  { [key in Component]: Vue.PluginFunction<never> };

declare const options: Options;
export default options;

type Color = 'red'
| 'pink'
| 'purple'
| 'deep-purple'
| 'indigo'
| 'blue'
| 'light-blue'
| 'cyan'
| 'teal'
| 'green'
| 'light-green'
| 'lime'
| 'yellow'
| 'amber'
| 'orange'
| 'deep-orange'
| 'brown'
| 'grey'
| 'blue-grey'
| 'white'
| 'black';

type ThemeOption = Color | {
  color?: Color;
  hue?: string | number;
  textColor?: Color;
};

interface ThemeType {
  primary?: ThemeOption;
  accent?: ThemeOption;
  warn?: ThemeOption;
  background?: ThemeOption;
}

declare module 'vue/types/vue' {
  namespace Vue {
    const material: {
      registerTheme(name: string | { [key: string]: ThemeType }, spec?: ThemeType): void,
      setCurrentTheme(name: string): void
    };
  }
}
Morgul commented 7 years ago

@akaSybe Right now, there isn't any typescript support on the roadmap, but we will discuss internally. I personally feel that the core developers' time is best spent on fixing our backlog of issues and implementing missing components, however we would gladly accept a pull request to add types.

waratah commented 6 years ago

I am using Typescript. There is a couple of other places to grab some definitions. Will helpi with this, self interest.

akaSybe commented 6 years ago

@waratah could you please share links to definitions you talk about?

Samuell1 commented 6 years ago

Hey, can you try new Vue Material 1.0.0 with TypeScript?

matths commented 6 years ago

in the meantime we can use npm install --save-dev git+https://github.com/calebsander/vue-material-types.git and use the definition from above more or less made available by @calebsander

Samuell1 commented 6 years ago

@matths that is outdated and only works for older version

crutchcorn commented 6 years ago

When V1 releases, I will likely try my hand at adding TS support. I would start working on it now but I'm fearful types will dramatically change before then

Saidabbos commented 5 years ago

vue-material/index.d.ts

import Vue from 'vue';

type Component = 'MdCore'
  | 'MdAvatar'
  | 'MdBackdrop'
  | 'MdBottomBar'
  | 'MdButton'
  | 'MdButtonToggle'
  | 'MdCard'
  | 'MdCheckbox'
  | 'MdChips'
  | 'MdDialog'
  | 'MdDivider'
  | 'MdFile'
  | 'MdIcon'
  | 'MdImage'
  | 'MdInputContainer'
  | 'MdLayout'
  | 'MdList'
  | 'MdMenu'
  | 'MdProgress'
  | 'MdRadio'
  | 'MdSelect'
  | 'MdSidenav'
  | 'MdSnackbar'
  | 'MdSpeedDial'
  | 'MdSpinner'
  | 'MdSubheader'
  | 'MdSwitch'
  | 'MdTable'
  | 'MdTabs'
  | 'MdToolbar'
  | 'MdTooltip'
  | 'MdWhiteframe';

type Options =
  { install: Vue.PluginFunction<never>} &
  { [key in Component]: Vue.PluginFunction<never> };

declare const options: Options;
export default options;

type Color = 'red'
| 'pink'
| 'purple'
| 'deep-purple'
| 'indigo'
| 'blue'
| 'light-blue'
| 'cyan'
| 'teal'
| 'green'
| 'light-green'
| 'lime'
| 'yellow'
| 'amber'
| 'orange'
| 'deep-orange'
| 'brown'
| 'grey'
| 'blue-grey'
| 'white'
| 'black';

type ThemeOption = Color | {
  color?: Color;
  hue?: string | number;
  textColor?: Color;
};

interface ThemeType {
  primary?: ThemeOption;
  accent?: ThemeOption;
  warn?: ThemeOption;
  background?: ThemeOption;
}

declare module 'vue/types/vue' {
  namespace Vue {
    const material: {
      registerTheme(name: string | { [key: string]: ThemeType }, spec?: ThemeType): void,
      setCurrentTheme(name: string): void
    };
  }
}

@CatsMiaow so how can I use then?

kenkopelson commented 5 years ago

@Saidabbos Thanks for putting that up there. One problem, however, is you import "Vue" at the top, but then try to use the same identifier "Vue" in the namespace at the bottom of the file. The compiler complains about this.

shoffing commented 5 years ago

@kenkopelson Changing Vue to VueM fixes that for me.

import Vue from "vue";

type Component = "MdCore"
  | "MdAvatar"
  | "MdBackdrop"
  | "MdBottomBar"
  | "MdButton"
  | "MdButtonToggle"
  | "MdCard"
  | "MdCheckbox"
  | "MdChips"
  | "MdDialog"
  | "MdDivider"
  | "MdFile"
  | "MdIcon"
  | "MdImage"
  | "MdInputContainer"
  | "MdLayout"
  | "MdList"
  | "MdMenu"
  | "MdProgress"
  | "MdRadio"
  | "MdSelect"
  | "MdSidenav"
  | "MdSnackbar"
  | "MdSpeedDial"
  | "MdSpinner"
  | "MdSubheader"
  | "MdSwitch"
  | "MdTable"
  | "MdTabs"
  | "MdToolbar"
  | "MdTooltip"
  | "MdWhiteframe";

type Options =
  { install: Vue.PluginFunction<never>} &
  { [key in Component]: Vue.PluginFunction<never> };

declare const options: Options;
export default options;

type Color = "red"
  | "pink"
  | "purple"
  | "deep-purple"
  | "indigo"
  | "blue"
  | "light-blue"
  | "cyan"
  | "teal"
  | "green"
  | "light-green"
  | "lime"
  | "yellow"
  | "amber"
  | "orange"
  | "deep-orange"
  | "brown"
  | "grey"
  | "blue-grey"
  | "white"
  | "black";

type ThemeOption = Color | {
  color?: Color;
  hue?: string | number;
  textColor?: Color;
};

interface ThemeType {
  primary?: ThemeOption;
  accent?: ThemeOption;
  warn?: ThemeOption;
  background?: ThemeOption;
}

declare module "vue/types/vue" {
  namespace VueM {
    const material: {
      registerTheme(name: string | { [key: string]: ThemeType }, spec?: ThemeType): void,
      setCurrentTheme(name: string): void
    };
  }
}
matsch01 commented 5 years ago

@shoffing I've created a folder called 'types' in my project with subdirectory 'vue-material':

+types
    +vue-material
        -index.d.ts (your code above here)
-tsconfig.json

and inside tsconfig.json I've added:

"typeRoots": ["node_modules/@types", "types"]

However, this line in main.ts gives an error:

import VueMaterial from 'vue-material';  <== Error here still.
Vue.use(VueMaterial);

Could not find a declaration file for module 'vue-material'. '/workspace/myproject/node_modules/vue-material/dist/vue-material.js' implicitly has an 'any' type. Try npm install @types/vue-material if it exists or add a new declaration (.d.ts) file containing declare module 'vue-material';ts(7016)

Can you explain how to load index.d.ts? Thanks.

maxhillaert commented 5 years ago

@matsch01 and others who hit this issue. The index.d.ts above is wrong. Import has to be inside declaration module. This is what works for me

declare module 'vue-material/dist/components' {

  import _Vue from "vue"; // <-- notice the changed import

  // export type PluginFunction<T> = (Vue: typeof _Vue, options?: T) => void;
  export function MdButton(Vue: typeof _Vue, options?: any): void 
  export function MdContent(Vue: typeof _Vue, options?: any): void 
  export function MdTabs(Vue: typeof _Vue, options?: any): void 
}
kamok commented 5 years ago

In regards to @maxhillaert's fix, here's a good answer on stackoverflow about this. https://stackoverflow.com/a/42702089/6174577

nsksaisaravana commented 5 years ago

Any roadmap to support typescript????

ghost commented 4 years ago

Any news on this? Proper Typescript support would be a huge improvement over native JavaScript (even though I love JS, partly because it's so f'ed up ;) )

ghost commented 4 years ago

@matsch01 and others who hit this issue. The index.d.ts above is wrong. Import has to be inside declaration module. This is what works for me

declare module 'vue-material/dist/components' {

  import _Vue from "vue"; // <-- notice the changed import

  // export type PluginFunction<T> = (Vue: typeof _Vue, options?: T) => void;
  export function MdButton(Vue: typeof _Vue, options?: any): void 
  export function MdContent(Vue: typeof _Vue, options?: any): void 
  export function MdTabs(Vue: typeof _Vue, options?: any): void 
}

Thanks for the information. Could you perhaps elaborate a bit? I don't see any trivial way to use your code sample, and if I just "show it in" I get the following message:

TS2665: Invalid module name in augmentation. Module 'vue-material/dist/components' resolves to an untyped module at '/home/rohdef/git/customer-web/node_modules/vue-material/dist/components/index.js', which cannot be augmented.

It might be my lack of experience with the TypeScript type definitons, but I'm kind of stuck

jameskleeh commented 4 years ago

@rfftrifork Running into the same issue. Did you ever find a solution? Pretty insane that after 3 years there is still no typescript support out of the box

Suyashtnt commented 4 years ago

@matsch01 and others who hit this issue. The index.d.ts above is wrong. Import has to be inside declaration module. This is what works for me

declare module 'vue-material/dist/components' {

  import _Vue from "vue"; // <-- notice the changed import

  // export type PluginFunction<T> = (Vue: typeof _Vue, options?: T) => void;
  export function MdButton(Vue: typeof _Vue, options?: any): void 
  export function MdContent(Vue: typeof _Vue, options?: any): void 
  export function MdTabs(Vue: typeof _Vue, options?: any): void 
}

I've tried this but it doesn't even say that my file exists. here is the repository with the bug: https://github.com/Suyashtnt/vuejs-weather

log:

PS C:\Users\Home\Documents\weather app> npm run serve

> vue-weather@0.1.0 serve C:\Users\Home\Documents\weather app
> vue-cli-service serve

 INFO  Starting development server...
Starting type checking service...
Using 1 worker with 2048MB memory limit
98% after emitting CopyPlugin

 DONE  Compiled successfully in 8198ms                                                                                                                                       14:29:40

ERROR in C:/Users/Home/Documents/weather app/src/main.ts(11,8):
11:8 Could not find a declaration file for module 'vue-material/dist/components'. 'C:/Users/Home/Documents/weather app/node_modules/vue-material/dist/components/index.js' implicitly has an 'any' type.
  Try `npm install @types/vue-material` if it exists or add a new declaration (.d.ts) file containing `declare module 'vue-material/dist/components';`
     9 |   MdContent,
    10 |   MdTabs
  > 11 | } from 'vue-material/dist/components'
       |        ^
    12 | import 'vue-material/dist/vue-material.min.css'
    13 | import 'vue-material/dist/theme/default.css'
    14 | 
Version: typescript 3.9.3
Time: 5095ms

  App running at:
  - Local:   http://localhost:8080/    
  - Network: http://192.168.0.100:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build. 
calvinnor commented 4 years ago

Running into the same error. Wish someone could add TypeScript support. I would, but I'm fairly new to the language.

Could not find a declaration file for module 'vue-material/dist/components'. '/home/project/node_modules/vue-material/dist/components/index.js' implicitly has an 'any' type.
  Try `npm install @types/vue-material` if it exists or add a new declaration (.d.ts) file containing `declare module 'vue-material/dist/components';`
bpossolo commented 3 years ago

pretty insane that no one has bothered to properly answer everyone's questions about this.... ignore basically everything you see above as its all outdated/wrong.

if you want to use specific components (recommended since it minimizes payload size) in your ts files: create vue-material.d.ts with the following lines (example for two material components)

declare module 'vue-material';
declare module 'vue-material/dist/components/MdButton';
declare module 'vue-material/dist/components/MdCheckbox';

place it anywhere under your source directory. I put mine in src/typings/vue-material.d.ts then in your ts app code simply do:

import MdButton from 'vue-material/dist/components/MdButton';
import MdCheckbox from 'vue-material/dist/components/MdCheckbox';
Vue.use(MdButton);
Vue.use(MdCheckbox);

if you prefer to load the whole library (kinda nuts) then do the following instead in vue-material.d.ts

declare module 'vue-material';

and in your code

import VueMaterial from 'vue-material';
Vue.use(VueMaterial);

note 1: when you import a specific component (like in the first example), you can't use the component like you normally do in a Vuejs components block. it only supports being registered globally as I showed in the examples above. ie this DOESN'T work

import MdButton from 'vue-material/dist/components';

export default {
  components: {
    MdButton
  },
  props: {
    name: String
  }
}

see here for a three-year old feature request regarding that.

note 2: for clarity, adding declarations via declare module doesn't bloat your js file. in fact, you can add every component to your vue-material.d.ts file to simplify your life down the road. but be mindful of how much you import/use because that will add to your js payload size.

cstergianos commented 3 years ago

You can use this on top of your normal npm installation: npm i git+https://github.com/calebsander/vue-material-types.git

Worked like a charm for me