-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
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
Typescript and Vue in general #478
Comments
Personally I haven't used TypeScript much; Vue requires some pretty special treatment in how its extend functionality works, so I need to look into how TS' class transpiling works first. On the other hand I know @diverted247 is working with Vue in TS a lot and he has https://github.com/diverted247/vuets which works with 0.10.6. You might want to take a look at that and join forces? |
I made a gist with my pattern: https://gist.github.com/indus/0c1ff6b4f4102a6286a8 |
Indus, the issue in extending Vue directly in TypeScript is the call to super. Vue implied (pre1.6) that configuration is passed in the constructor yet this proceeds TS class member creation. The fix was to add support to Vue to pass false to the constructor and defer configuration to a call to Vue.init( config ). The change allows you to then map a TypeScript class into Vue with no side effects. We are using it in production and are seeing very few limitations. Key logic is here https://github.com/diverted247/vuets/blob/master/todomvc/js/app.ts |
In 0.11 the I think this should make TS integration a bit easier than 0.10. What do you guys think? |
I missed that change in V0.11 |
diverted247, how can i merge options in your code? Lets say I create something that needs a "ready"-funktion in its internal setup, but you also want to give a user the possibility to paste in their own options as well, with another 'ready'-function for example ( |
TypeScript just needs a way to:
TypeScript class instances create members after the call to super and thus I am 100% ok with the team breaking VueTS to make Vue better. I can adapt Ted :) On Mon, Oct 27, 2014 at 4:01 AM, indus notifications@github.com wrote:
|
I made a gist for the pattern i use (with a basic definition file): I use this in all of my vue-projects and it works perfect for me, even subclassing (this got even better with TS 1.3 and the diverted247 made a nice comparisson (https://github.com/diverted247/vuets) of the two possible aproches. To sum it up from my perspective:
I think the second approach (done like shown in my gist) is way superior, because writing the definition files is always a weak point in using TS. Only few have the passion to write them, and keeping them up-to-date is constant work. With the class-approch you get your definitions while you are writing you code and it stays in sync to your development. But as I said, until TS or Vue make a significant move towards the other, it all depends on your paradigm: "no hacks" or "no affort" I think making Vue fit to TS wont be painless and affects parts in your code I don´t fully oversee, but would maybe also be worth the trouble. |
Hi, does anything changed with Vue 0.12.x introduction? We have a business need to use TypeScript. Application it self have to be made of set of small to medium size independent, decoupled components, so Vue looks like a natural choice here. But lack of TS support is a big blocker for us. RivetsJS looks like abandoned, so that's not an option neither, however it's way to bind any JS object with any jQuery node object is nice and in fact it solves the problem. Is it possible in Vue to implement (in reasonable time amount) such behavior? I mean implementing it in some If not, are there any other options? As far as i can tell, by quick looking at Vue's code, the As to the above solutions from @indus and @diverted247 - not sure i understood it correctly, byt - i must say that we're on a beginning of a big app rewrite and the feelings are strong to avoid hacking and unusual use of libraries, so really - we're not happy to hack Vue extend concept this way. Anyway @indus and @diverted247, did you manage to solve this some other/better way? And @yyx990803 how do you think if it's possible/reasonable to alter Vue's extend mechanism? And how hard eventually it would be? |
@sl-codenine now that I think about it, it would be possible to simulate @component({
// Vue.extend() options here...
})
class MyComponent extends Vue {} Or, declare the options as a static property and simply add a decorator: @component
class MyComponent extends Vue {
static options = {
// options here...
}
} Maybe even make it look more "classy" if we do a bit more plumbing in the decorator (not sure if feasible): @component
class MyComponent extends Vue {
// data
msg = 'hello!'
// method
greet() {
console.log(this.msg)
}
// computed
get computedMsg() {
return 'computed ' + this.msg
}
// lifecycle hooks (reserved method names)
ready() {
this.greet()
}
// assets
static directives = { /* ... */ }
static filters = { /* ... */ }
// other options
static options = {
// other options here...
}
} In the end a Vue subclass is defined as:
And obviously, this requires using TypeScript 1.5+ |
One issue with VueTS is that you end up fighting the internal nature of Vue. Vue has an elegant api in use of JS objects but cramming that into TS via Classes or TS Language features may not be the best choice. I have been using Vue 11/12 with TS by simply typing the values directly and not using class/modules. I would love to see deeper integration with TypeScript but something is lost in the process. Unless it is done from the ground up similar to Angular2 approach. One key issue is the misalignment of model definitions and model instance use within Vue. This makes the TS compiler go stir crasy as model properties are created in one place, yet used at runtime somewhere else. This mapping is hard to wrap with a TypeScript definition as the properties are app specific not something Vue has knowledge of. Take this example...
TypeScript can see .el and .data but .message is part of the app model definition. The problem comes when demo.message is set as TypeScript does not know where this came from and thus it is clearly an error( compiler perspective). The VueTS solution was to have a class extend Vue and define properties as class members thus the instance API is in sync with the class definition. It was sort of favoring the vue instance API and generating the Vue constructor api to suit. Works but not ideal. I am pretty sure there is a great solution here. I would love to see TS and Vue work closer together and would be happy to help. I have 3 projects using Vue+TS and would love to have a better solution. Ted :) |
Have you thinked about GWT +Vue? I have a small project on my github repos test uses Vue and Gwt and generate application skeleton at compile time. If TS is not a requirement it would be a nice solution for Java developers. |
@muten84 I've never used GWT, so I honestly have no idea what is needed to make it work with Vue :/ |
BTW, I was able to write the decorator I talked about, albeit transpiled as ES7 using Babel: https://github.com/vuejs/vue-class-component The same decorator should work for TS too, but I'm not familiar with TS' packaging/build setups. If any of you want to try adapting to to TS, you are more than welcome to do so. |
It seems that i was going off-topic, I'll try to explain better: Typescript and Java have the same features so i mentioned GWT because it enables to compile Java source code in Javascript code. Furthermore GWT let you to reuse all your pre-existent Javascript code in your Java code. If interested i can make a fork and contribute in a Java version API :) Having both VueGwt and VueTs it would be great :) |
@muten84 you are more than welcome to do so if you find that useful, although I probably won't be able to help much since I don't use GWT nor java. |
@sl-codenine: I´m still using the TS-Class based approch and it works well for me in a couple of projects. I only made a few adoptions to reflect newer versions of TS (e.g. union types) and Vue (e.g. a newer version of the TS definition file that can be found here). Even I never had any problems with it I would be more then happy to see a "first class" support. |
@yyx990803 @indus @diverted247 @muten84 Sorry for my late response, didn't have much time to test all the options. Anyway thanks for your help. It helped a lot. Overall decided to go with the class decorator pattern, as it looks to me it's the less invasive for the rest of TS code, as it needs only @yyx990803 I managed to make it work with TS 1.5, i mean your I'm ready to work on it some more to make it usable for everyone, and basically that's my business too. As for now i've done some basic transformations to make it more TypeScript-ish, and removed the P.S. Wouldn't it be better if you provide write access to |
@sl-codenine cool! Glad you can get it working. The Public write access sounds a bit... too open. Fork and PR is pretty standard imo, since in the long run we may just use it as the official recommendation for TS users. |
For anyone interested in TypeScript support for VueJS, you can get the TypeScript declaration file from https://github.com/borisyankov/DefinitelyTyped. The easiest way is to install the NPM module tsd. Then your can just do:
That will create a directory for typings, as well as a tsd.d.ts file that your can reference in your JavaScript file or at the top of a block of JavaScript so that editors that have TypeScript capabilities can understand Vue code. This works especially well with Github's Atom browser with the TypeScript plugin, as well as Microsoft's new cross-platform code editor, Visual Studio Code. @yyx990803, TypeScript declaration files enable editors to understand the JavaScript and parse it to enable code completion, hits, and intellisense. Creating a TypeScrpt declaration file is not difficult, I've done several myself. It's basically just a collection of interfaces that define the parameters and return values of object and functions in a library. The current version of Vue on DefinitelyTyped is for vesion 0.11.0. |
What if we go further?
import Vue, {elementDirectives, components, listen, watch, on} from 'vue';
@elementDirectives(EvilIcon)
@components(Player)
export class App extends Vue {
/* I really think this should be only static properties here */
static inherit = true;
static props = ['test'];
/* Maybe let's go further with async components? */
async data () {
this.className = 'app';
this.model = await fetch(dataUrl);
}
/* we're replacing one-time bindings by instant binding. Should not it be faster? I'm really curious */
render () { return `<div class="${className}" v-on="click: onclick"><EvilIcon/></div>`; }
/* event listener. OK, we're limiting it to one and making us unable to rely upon shorthand syntax watch: {ready: 'reload'}, but it's fine */
@listen('ready')
onReady () { console.log("I'm ready!") }
/* Actually, we do not need element name - Ember problem :(. So maybe something like this will be also good? */
@listen
ready () { console.log("I'm ready!") }
/* update listener. Same logic */
@watch('model')
onModelUpdate () { console.log("Model updated?") }
/* You see what I mean? */
@on('click')
onClick() { /* some action */ }
get hello () {
return 'hello';
}
changeModelInfo () { /* just method */ }
} |
@Jabher interesting ideas! The decorator I made was also experimental, you should feel free to make your version. |
@yyx990803 what do you think? It's a bit fast-n-dirty, though working good. Also it needs more integration as far as it's just wrapper. Example code const {components, on} = VueComponent;
class test_component extends VueComponent {
static template = '<div>I\'m a component!</div>';
}
@components({test_component})
class App extends VueComponent {
static template = '<span>message is: {{message}}<br/><test_component></test_component><input v-model="message"/></span>';
data () {
return {message: 'hello'}
}
ready () {
console.log(this);
this.message = 'Its working!';
}
}
new App({el: '#main'}); Ideas about async data and template generation are more about deep integration, so I did not try to implement them for now |
We are using the following syntax for vue components written in TypeScript: // load the decorators
/// <reference path="src/vue-component.ts" />
// destruct the decorators from the VueComponent
const {createComponent, prop, lifecycleHook, eventHook} = VueComponent;
// transform the class Demo to a vue component called demo
@createComponent('demo')
// the VueComponent.Base provides all the declarations, Vue provieds to the component, the makes sure
// TypeScript support type checking and autocomplete
class Demo extends VueComponent.Base {
// transforms to option.template
static template:string = '#demo-template';
// transforms to option.replace
static replace:boolean = true;
// the @props decorator transforms a property to an attribute
// for the supported options see http://vuejs.org/api/options.html#props
@prop({
type: Boolean,
required: true
})
option:boolean;
// normal properties, pass through the data options are declared as normal properties
property:string = 'foo';
// the @lifecycleHook decorator supports the following hooks:
// created, beforeCompile, compiled, ready, attached, detached, beforeDestroy, destroyed
@lifecycleHook('compiled')
compiled():void {
// ...
}
// the @eventHook decorator registers the decorated method as event listener
@eventHook('listen.to.event')
eventListenToEvent():boolean {
// ...
}
// normal methods are declared as class members
method(arg:string):void {
// ...
}
// computed properties are defined as getter and setter
get computed():number {
// ...
}
set computed(arg:number) {
// ...
}
} I've put up a github repo with a tiny library and some examples (derived from the original vue examples) |
@yyx990803 I would disagree.
Looks like there's one obviously preferable way to implement es6-classed Vue. And it would be really good idea to make it bundled by default. I'll be happy to help you with it (it will take some amount of time to re-write parts of the app to es6). Actually, I've been checking out the Vue code during the weekend and I have a strong feeling that the following options is possible: |
@Jabher imo Vue should ship a lean core that runs in ES5 environments and that's it. Anything that assumes ES2015/transpilers should be shipped as a plugin. I think it's possible to have a "reference implementation" for a class interface, but I don't want to make it "the only way to use Vue with ES2015/TS". |
Is that a temporary decision as long as we need transpilers, or would that stay in effect even after we have widespread native support for ES2015? |
It would still be nice to be able to use TypeScript in Vue files as well. As far as I know that's not possible right now. |
@amcsi There is vue-ts-loader to use TypeScript in single file component. |
Oh wow! |
There is also an introductory guide for Vue-TS integration. Check it out! |
After working with it, i wouldn't recommend it. Encountered too many bugs so far. Use https://github.com/locoslab/vue-typescript-component-example instead. |
@Ansien12 would you please file bugs on related projects? I'm curious about them. |
Just curious: For people in this thread, are you interested in Type Safety in Vue Component, or just IDE features such as auto-completion (e.g., prompt all Because I feel TS + Vue isn't a prerequisite for implementing IDE features. I've been writing my projects using JS/ES6 for Vue Component and TS for everything else. So far my feeling is
Although I appreciate @itsfrank and @HerringtonDarkholme's work, I wouldn't use vue-typescript as keeping template/style/script in visual proximity (same file) is important for me. av-ts looks more promising, but I find the benefit it brings (as of now) doesn't outweigh the complexity it brings in. |
I understand you arguments regarding having a hard time making ts and VueJS work fully together, and why a more pragmatic approach may seem more sensible. I like to have the auto-complete feature working, but building production code in pure TS, makes me sleep really good at night :-) It seems like we are so close, if only the we could get the ES6 class So, maybe what would help (correct med if I am wrong), is to have a few
As far as I understand it, the biggest unresolved issue is that we can only use tsx file via On the other hand, all core vue2 component has ts support now, and we are so close to be able to make ts integration nearly painless, so I hope my next project will make use ar ALL these ts goodies. |
@druppy have you gotten the spread operator to work in JSX? I am running into an issue which I posted here: vuejs/babel-helper-vue-jsx-merge-props#3 |
It might be quirky but I found just setting vue SFC's file type to typescript is enough for editors to give semantic completion. (though highlighting is lost). It works in VSCode and Vim. |
@HerringtonDarkholme Would you mind sharing a screenshot for VSCode? |
VSCode: Usefule comment from mhegazy: microsoft/vscode#14032 (comment) My guess is that TS service is robust enough to ignore those html tags. And editors are just sending |
Well, that's Salsa giving a best guess. In Nov/Dec VSCode plans to restore JS support in HTML, and I will write a Vue language server based on VSCode's HTML language server, which will leverage Salsa and enable IntelliSense and other language features for JS/TS in Vue's SFC. I wouldn't go into details here to digress from the topic. If you are interested open an issue at https://github.com/octref/vetur and we can continue our discussion over there. |
@SeanJM Nope, I was a bit turned off by the fact that I need to use both TS and babel. But I hope the new |
@druppy I debugged it and posted a working configuration as a gist here: https://gist.github.com/SeanJM/263f9dda94ed6e9bf4323bd0b136de73 |
I know people in this thread are gonna love this 😝 |
Thank you very much for sharing this @octref |
Thanks @octref! I played with it a bit, and I really like having proper typescriptin' inside |
@zigomir It's very experimental and a WIP so I wouldn't say it's a good idea to distribute it widely, yet. See more context here: vuejs/vetur#94 (comment) But the future is bright. With TS definitions I can provided much better semantical IntelliSense / type-checking in both |
Current Vue.js default webpack templates support some CSS preloaders almost out-of-box (you only need to I wonder if the same could be done for TypeScript, so one can start writing TypeScript-based components with no extra changes in Webpack config (even letting TypeScript-based components coexist with Babel-based ones). I'm quite close to achieve this objective in my experiments with a local project, but I still need to rename the entry point |
I believe people come around to this post still, 3 years later. I wrote an article on Medium describing how to optimally setup Typescript with Vue (using the Webpack starter) https://medium.com/coding-blocks/using-typescript-in-your-vue-app-c4aba0bbc8bc |
Are there typings for Vue.util? or is not recommended to use Vue.util? |
After opening the issue - almost exactly 3 years ago - I haven't commented here alot and I know the issue is closed for a while but I just have to say that the improvement in v2.5.0 is the solution I've dreamed of and I wanted to thank the people making it possible. 👏 FYI: https://medium.com/the-vue-point/upcoming-typescript-changes-in-vue-2-5-e9bd7e2ecf08 |
Now I need to love typescript in Vue? Mental. |
I have a small problem; I'm in love with two things at the same time: Typescript and Vue.
I tried a handfull different approaches to make them work together; using TS modules and/or classes with public/private/static properties to shim vue components is the best i got.
I love the intelisense, autocompletion and error hints i get by doing so!
But after all it is kind of hacky.
I wanted to ask you what you think about Typescript? Do you think it is possible to bring them togeher in a more natural way?
Maybe refactoring some parts of your extend routine (to make some of its internals reachable from a typescript construtor) could make a huge difference.
The text was updated successfully, but these errors were encountered: