Typescript and Vue in general #478

Closed
indus opened this Issue Oct 10, 2014 · 118 comments

Projects

None yet
@indus
indus commented Oct 10, 2014

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.

@yyx990803
Collaborator

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?

@indus
indus commented Oct 24, 2014

I made a gist with my pattern: https://gist.github.com/indus/0c1ff6b4f4102a6286a8
and maybe it helps somebody else, too.
after all I think there is little you can do to bring Vues "extend" and TSs "extend" closer together.

@diverted247

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

@yyx990803
Collaborator

In 0.11 the Vue.extend logic has been greatly simplified (the option merging is externalized from the constructor, all constructors simply call this._init): https://github.com/yyx990803/vue/blob/0.11.0-rc3/src/api/global.js#L27-L45

I think this should make TS integration a bit easier than 0.10. What do you guys think?

@indus
indus commented Oct 25, 2014

I missed that change in V0.11
Thanks you

@indus
indus commented Oct 27, 2014

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 (constructor(instanceOpt?)).
Maybe 'mergeOptions()' from the Vues extend-procedure should be available in Vue.util? But where should it be called? On every instantiation seems wrong.

@diverted247

TypeScript just needs a way to:

  1. Subclass Vue via prototype
  2. Pass configuration to instance not via constructor.

TypeScript class instances create members after the call to super and thus
creates a subtle timing issue. Vue could only be instanciated by passing a
configuration via constructor so subclasses would fail when attempting to
pass members to super before they existed. <insert chicken & egg joke>
Solution was to pass super(false) to Vue, then call a separate Vue method
to set the configuration via the subclass.

I am 100% ok with the team breaking VueTS to make Vue better. I can adapt
if there is an external way to set configuration in Vue.

Ted :)

On Mon, Oct 27, 2014 at 4:01 AM, indus notifications@github.com wrote:

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 (constructor(instanceOpt?)).
Maybe 'mergeOptions()' from the Vues extend-procedure should be available
in Vue.util? But where should it be called? On every instantiation seems
wrong.


Reply to this email directly or view it on GitHub
#478 (comment).

@indus
indus commented Dec 20, 2014

I made a gist for the pattern i use (with a basic definition file):
https://gist.github.com/indus/0c1ff6b4f4102a6286a8

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 protected modifier).
But although I have to say that this is not the "holy grale" and the only truth.

diverted247 made a nice comparisson (https://github.com/diverted247/vuets) of the two possible aproches. To sum it up from my perspective:

  1. use a module: straight forward, almost no benifits over plain JS
  2. misuse a class: a small hack, get benifits from TS like intellisense

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.

@sl-codenine

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 real and vue-native way, not by embedding custom object inside VueComponent object, or anything like that, which will most likely cause some problems down the road anyway.

If not, are there any other options? As far as i can tell, by quick looking at Vue's code, the .extend() concept goes quite deep. Can't see an easy solution for that.

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?

@yyx990803
Collaborator

@sl-codenine now that I think about it, it would be possible to simulate Vue.extend using annotations (similar to how Angular 2 does it):

@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:

  1. Prototypally inheriting Vue;
  2. Having a static options object that contains the component options. There's a "merge" step which is what happens in Vue.extend, but we can do that in the decorator by extracting the options from the class declaration (it seems we can only do that for static properties?)

And obviously, this requires using TypeScript 1.5+

@diverted247

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...

var demo = new Vue({
    el: '#demo',
    data: {
        message: 'Hello Vue.js!'
    }
})

demo.message = "Hello Vue.ts!";

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 :)

@muten84
muten84 commented Jun 25, 2015

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.

@yyx990803
Collaborator

@muten84 I've never used GWT, so I honestly have no idea what is needed to make it work with Vue :/

@yyx990803
Collaborator

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.

@muten84
muten84 commented Jun 25, 2015

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 :)

@yyx990803
Collaborator

@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.

@indus
indus commented Jun 26, 2015

@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).
But it is the same hack: using TS-classes to inherit from Vue as it would be be the normal way - block TS extend function - extend manually with Vue.

Even I never had any problems with it I would be more then happy to see a "first class" support.

@sl-codenine

@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 @component annotation and that's it.

@yyx990803 I managed to make it work with TS 1.5, i mean your @component solution, and created PR for that. It would be cool if you can confirm that's correct and it will work down the road. It looks like it is working indeed, but at the very end no one knows Vue better than you, so maybe you'll see some possible problems.

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 clone() part as it was introducing maximum call stack size exceeded error and basically i'm not sure if that was necessary anyway?

P.S. Wouldn't it be better if you provide write access to vue-class-component for everyone, just not for the master branch, so one can contribute - to such a small and "example style" repo - without the need to fork?

@yyx990803
Collaborator

@sl-codenine cool! Glad you can get it working.

The clone() is necessary to make sure each instance gets a fresh copy of the initial data, otherwise the same data object is shared among all instances of that class. (in ES6 the Class function cannot be called as a plain function, otherwise it would be easier.) It needs a bit of work to deal with the maximum call stack issue, likely because it's not handling circular references.

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.

@sourcebits-robertbiggs

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:

tsd install vue --save

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.

@Jabher
Jabher commented Jul 30, 2015

What if we go further?
A bit more "reacty" and "fluxy".

  1. Classes are flat-extendible. So that we will need to remove all the data stuff.
  2. Decorators are really powerful things, we can use them heavily.
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 */ }
}
@yyx990803
Collaborator

@Jabher interesting ideas! The decorator I made was also experimental, you should feel free to make your version.

@Jabher
Jabher commented Jul 31, 2015

@yyx990803 what do you think?
http://jabher.github.io/vues2015/

It's a bit fast-n-dirty, though working good. Also it needs more integration as far as it's just wrapper.
Slow loading is due to nothing is compiled and babel is compiling everything in browser, it's just fast attempt.

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

@gamperl
gamperl commented Aug 10, 2015

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
Collaborator

@Jabher @gamperl very cool! Now I'm pretty sure we don't (and shouldn't) need one official class interface for Vue components. Most of us would have our own subtle preferences, but the beauty of it is you can easily create your own interface on top of Vue with transpilers.

@Jabher
Jabher commented Aug 10, 2015

@yyx990803 I would disagree.
Not every person will make a good implementation, it will take significant amount of time, and I'm not sure that something of that kind - something more than just dumb wrapper will appear soon.
Anyway, deep integration is always better (at least for performance). Speaking about Vue - it is really looking like it's made to be es6-ified. BTW, @gamperl, looks like you're not caching anything, also how do you bind a local components/directives/filters?
Also Object.getOwnPropertyNames, then iterating through property descriptors - sounds like kind of bad idea, especially in serious projects, and we both are doing it. Caching can help in it, but not solve it fully.
So, about implementation.

  1. We both are relying upon event decorators, either @on or @eventHook, it's not so important.
  2. We both are using getters and setters for computed properties, and methods for, em, methods.
  3. We do not override constructor, we're just using annotations and methods/props.
  4. We're both using static attributes for template and inherit.

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:
I would propose to restructure application a bit, then create 2 endpoints, one will be creating classic Vue interface, another one will expose Vue class for es6. It is possible (though a bit complex, but endpoints footprint can be rather small so maintainability will not become worse). So that users can both make var Vue = require('vue') and import {Vue} from 'vue/class';

@yyx990803
Collaborator

@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".

@JosephSilber

Vue should ship a lean core that runs in ES5 environments and that's it.

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?

@yyx990803
Collaborator

@JosephSilber you can call it "temporary", but native ES2015 support is pretty dismal at the moment; and judging from how long it took for ES5 to be universally supported, I'd say it will take another 3~5 years before widespread ES2015 adoption without the need for transpilers. In addition, the current class interfaces all rely on stage 0 proposals (property initializers) that are not part of ES2015. By that time Vue would probably have been rewritten in pure ES201X already.

@JosephSilber

Or ES202x 😭

@yyx990803
Collaborator

@JosephSilber haha, or something that replaces JavaScript ;)

@JosephSilber

WebAssembly? Maybe you can write it in Go 😄

@Jabher
Jabher commented Aug 10, 2015

@yyx990803 we all know that cool guys are actively using babel mostly, so looking at compatibility table is not a best idea :) There's a guys in front of me which are making a big ecommerce app (for US company with hundreds or thousands of shops worldwide) on Ember with babel for internet explorer 9+.

Transpilers are already adopted even in a lot of big corps, so using them is becoming good practice right now.

@Jabher
Jabher commented Aug 10, 2015

@JosephSilber let's go clojure, yeah! 😄

@yyx990803
Collaborator

@Jabher that's exactly what I mean, you need transpilers to make it work. Vue core should only contain parts that do not rely on transpilers, so the class interface should ship separately.

@Jabher
Jabher commented Aug 10, 2015

@yyx990803 Dammit, I just understood I'm an idiot. Vue supports prototype extension. You literally should make nothing but decorators for events and so on. No Object.getOwnPropertyDescriptors and other stuff.

class Test extends Vue {
    test () { document.body.innerHTML = 'working!'; }
}

new Test({
    el: 'body',
    ready: function(){ this.test(); }
});

Man, all that is needed for the support is just a few decorators, even not relying upon the main app :) I'll make a PR tomorrow if you don't mind.
Usage will be something like

import Vue from 'vue';
import {components, directives} from 'vue/decorators';
@components({someWidget})
class Component extends Vue {...
@yyx990803
Collaborator

@Jabher Please make it a standalone module. As I said before, I don't want Vue-core to be install-it-and-you-get-everything; e.g. vue-router and vue-resource are all separate packages. Vue-core can be used without them, but can be used together if needed. Same for decorators.

@gamperl
gamperl commented Aug 10, 2015

@Jabher My implementation is not feature complete, it is just a proof of concept.
How do you want to separate between methods and computed properties without using getOwnPropertyNames?

@Jabher
Jabher commented Aug 18, 2015

@gamperl you actually do not need to. Both of them are later becoming just prototype properties.
So it's simply double work.

On other hand I'm continuing to investigate all that stuff and see now that everything here is kind of over-complexified and is kind of blocking the implementation in details.

@styfle
styfle commented Oct 27, 2015

Great discussion! I just heard of Vue.js today and I am quite fond of TypeScript like many of you.

It seems like none of these implementations provide type safety in the template string (something that was recently added in TS 1.6 with TSX/JSX support).

Might I suggest something like the following:

class Person {
    public className = "my-class";
    constructor(public first: string, public last: string, public age: number) {
        this.className = "some-other-class";
    }

    public getFullName() {
        return this.first + ' ' + this.last;
    }
}

function render(p: Person) {
    // Type safety!
    // Refactoring methods or vars won't silently break
    return `<p>
        Greetings, ${p.getFullName()}.
        Next year, you will be ${p.age + 1} years old!
    </p>
    <div class="${p.className}">
        First: <input v-model="${p.first}">
        Last: <input v-model="${p.last}">
    </div>`;
}

// Our data is member variables + methods
var data = new Person('John', 'Doe', 25);

// Suggested 
var demo = new Vue({
  el: '#demo',
  data: data,
  render: render
})

Does this seem plausible or will this fail to use the Vue.js binding since v-model will be assigned the value and not the property name?

@kaorun343
Contributor

Hello.
I wrote the type definitions of vue-router.
https://gist.github.com/kaorun343/684b7770fc9cb4fcb40a
If there are anyone here who would like to add the file to definitely typed, please inform me.

@auvipy
auvipy commented Nov 9, 2015

what about coffeescript?

@Jabher
Jabher commented Nov 9, 2015

@auvipy what do you want for coffee script?

@auvipy
auvipy commented Nov 9, 2015

writing vuejs apps in coffeescript

@styfle
styfle commented Nov 15, 2015

After spending some time thinking about this problem, I came up with a simple solution for typed templates: typed-tmpl

I haven't implemented all the features of vue at this time, however it is a good Handlebars replacement.

@gamperl
gamperl commented Nov 16, 2015

Well, you wrote an independent template engine, whats the connection to vue?

@martinsura

+1 for support typescript :)

@kaorun343
Contributor

I've wrote some more definitions
https://github.com/kaorun343/vue-typescript
I haven't tested all of the definitions, so there might be some mistakes.

@mindplay-dk

I've been tinkering, and I think the problem is the separation of data and methods as two members of an object being passed to e.g. Vue.extend() - I struggled for a few hours trying to create a generic type definition that would make TypeScript understand that this inside functions in methods may refer to either members of data or other members of methods, but I don't think that's possible. (it looks like they're working on a feature that lets you define the type of this in function calls, but that's not currently a feature...)

So, here's a different idea - what if we take an actual class and pull it apart using a decorator?

Basically, just write a model part naively, as a plain class, without Vue... I got this far:

https://jsfiddle.net/p3795yzo/1/

What we would want to pass as data and methods is in there (as you can see from the console.log() statement) so it should be possible to pull this out and pass it to Vue.extend() along with filters and other things that aren't important for type-safety?

I don't really know what I'm doing. I just know that what I've seen so far doesn't work for me - with something like Vue.extend() and passing an object with methods and data, there's no actual type-checking internally in that structure, e.g. assertion that data members being accessed from methods even exist, which defeats the purpose of using TypeScript.

Simply checking the of structure being passed to data and methods is crude and rather uninteresting - we need to find some way to write models that will actually get checked...

@gamperl
gamperl commented Jan 7, 2016

@mindplay-dk a few month ago a wrote a prove of concept for this idea: https://github.com/usystems/vuejs-typescript-component . We are using decorators similar to the ones on github in our production code and it works perfectly.

@ayosec
ayosec commented Jan 9, 2016

@gamperl

https://github.com/usystems/vuejs-typescript-component . We are using decorators similar to the ones on github in our production code and it works perfectly.

Thanks for sharing!

@kaorun343
Contributor
@mindplay-dk

So many ways to approach this... honestly, I wish Vue would just go the Angular way and port the whole thing to TypeScript - it's so much better for large projects...

@indus
indus commented Jan 14, 2016

@mindplay-dk I just read your post about using a class as VueOptions. You may want to have a look at the pattern I proposed about a year ago https://gist.github.com/indus/0c1ff6b4f4102a6286a8
May be a bit outdated - but I´m still using something similar after all the time

@mindplay-dk

I think what I like best so far is what I've seen from @gamperl - the only thing I would do differently, is for things that don't matter to the type, such as lifecycle event handlers and formatters (which aren't used by the actual methods of the class) I wouldn't define those as static members or methods with decorators, since they don't matter as such, I would probably define an interface with a fixed set of callbacks, for example one that returns the list of formatters, with a defined type.

But I think that's the problem, is everyone would come up with something slightly different - it's not conducive to building community, if everyone is running in a different direction.

Also, it seems like every solution we come up with works for one class, internally - what about multiple components working together? I think this is very hard to address by starting with classes and trying to transform them into Vue components using decorators and other run-time transformations.

I think that, trying to apply type safety as an afterthought, for something this complex, isn't really a viable approach. I'm betting that's one reason the Angular team moved to Typescript - if you want something that comfortably scales to big projects and large teams, plain JS with lots of doc-blocks and external documentation just isn't the best way to go about it...

@gamperl
gamperl commented Jan 19, 2016

We are using annotated typescript classes for vue in a fairly big project and it works perfectly. We didn't experience any problems with complexity up to now.

I personally really like typescript and our company mostly using typescript, but for a project like vue, it makes totally sense to use plain JS. By using typescript you restrict the usage to the typescript community and make it harder for most people to start with it.

@mindplay-dk

By using typescript you restrict the usage to the typescript community and make it harder for most people to start with it

I think that's a strange point of view, and were that true, I think Typescript would likely have no audience at all. Switching to Typescript didn't affect the AngularJS community - plenty of people continue to use the compiled JS, just as they were using the pre-built JS before.

The whole point of Typescript, is that it's essentially Javascript with type annotations - the output is plain JS, which is essentially the Typescript with the type annotations stripped, e.g. same as what you would have written in plain JS anyhow. The main difference between plain JS with JSDoc and Typescript, is a far superior type system, a stronger type-checking tool, and much better design-time (IDE) feedback providing higher productivity for those who use Typescript.

As a consumer, you don't have to ever look at the Typescript code - you can take the pre-built JS code and work with that. That's how most people consume JS libraries to begin with, whether they were built from pre-processed plain JS, Typescript, Coffeescript, or something else.

Anyhow, just my point of view, and I don't wish to have a long language debate, but I really don't feel that JS is suitable for many of the more complex things it gets used for today. We have better options.

@blake-newman
Member

@mindplay-dk wouldn't agree any less other than these is a clear identity of ng1 users migrating to alternative frameworks due to a move to typescript.

In the end all compiling languages for JS, end up being JS right? Anyhow I think support for these languages should be looked at, to help grow the community, however using typescript to build view won't necessarily solve anything other than bloat out the compiled distribution version.

@mindplay-dk

using typescript to build view won't necessarily solve anything other than bloat out the compiled distribution version.

You clearly have not really used TypeScript.

@gamperl
gamperl commented Jan 22, 2016

I think this is not the right place to start a flame war! @yyx990803 has expressed earlier, that he will not move vue to ts. So we should discuss, how to provide a nice ts interface to vue. Every thing below that is pointless.

@yyx990803
Collaborator

What @gamperl said ;)

@kaorun343
Contributor

Hello.
What do you think about adding TypeScript definition files into each repository?
The current version of vue-class-coonent contains the definition file.

@yyx990803
Collaborator

@kaorun343 is it possible to distribute definition files separately? Ideally I want to keep them separate because Vue itself is not written in TypeScript. But having them available for VS/VSC users is nice.

@kaorun343
Contributor

@yyx990803
If it is needed to separate, we're going to utilize DefinitelyTyped or copy and paste.
But if these files are included, we don't have to download them manually.

I would like to hear more opinions about this from more people. I really wonder if there're people who hopes to do so, other than me.

@yyx990803
Collaborator

@kaorun343 DefinitelyTyped sounds like a better idea to me.

@diverted247

Having worked with both TypeScript(3+ yrs) and Vue(1+ yrs)...

My thoughts:

  1. Publish VueJS definitions to Definitely Typed. I do not trust d.ts if
    they are not published there, unless I wrote it.
  2. Generate an app.d.ts specific to your app viewmodel/api with Vueify.

The frustrating part of VueJS + TypeScript is the dynamic nature of the
VueJS api. The viewmodel generates the api at runtime (getter/setters) in
an alternate location and methods/events are scoped to the ViewModel not
the code structure. TypeScript cannot understand this shift unless it is
informed and thus it either needs a remapping of the model api (what
https://github.com/diverted247/vuets does) or it needs a d.ts file that
denotes the app api. I believe Vueify can generate the d.ts file and could
help assert type conformance on both use of the viewmodel and
method/filters/templates/events. That feels to me to be the right path to
go.

Vue does not need to be written in TypeScript, Vue's api should not change
if using typescript (API 1:1) or babel, but enabling the generation of a
typescript definition file specific to the .vue file would provide many
benefits... autocompletion, model errors during development, method errors,
template errors (see react's .jsx/.tsx ).

I have thought about this allot and in hindsight, contorting Vue into TS
structures was not ideal. Today generating a d.ts to enhance vuejs use
feels more along the path I would like to see.

Ted :)

On Thu, Feb 4, 2016 at 12:31 PM, Evan You notifications@github.com wrote:

@kaorun343 https://github.com/kaorun343 DefinitelyTyped sounds like a
better idea to me.


Reply to this email directly or view it on GitHub
#478 (comment).

@mindplay-dk

@diverted247 +1 this:

The frustrating part of VueJS + TypeScript is the dynamic nature of the VueJS api

I have thought about this allot and in hindsight, contorting Vue into TS structures was not ideal. Today generating a d.ts to enhance vuejs use feels more along the path I would like to see.

Very insightful - I think this pretty much nails what I feel has been missing from the various third-party .d.ts files and accompanying "contortion" code, mixins, etc.

Whether I "trust" any of these libraries or not, the approach of contorting Vue to match TS (and typical) OO patterns may in deed be why I still fear making it a cornerstone of big TS projects. (I have seen this sort of thing go wrong more than once, and since I started writing TS a few years ago, using plain JS on large projects is just not something I can get behind anymore...)

@chrisvfritz
Member

@diverted247 @mindplay-dk Would love to hear what's missing from the latest DefinitelyTyped definitions. No one on the core team is a heavy TypeScript user, but we do recognize that it's useful for a lot of projects and want to do what we can to support it. 😃

@druppy
druppy commented May 4, 2016

It would be nice if vue-class-component and the latest definition was in sync.

This is IMHO the only thing that dont make Vue a no brain choice, that Vue dont not use ES6 classes (its own extend and constructor is not called), and make a somewhat parallel class system. If vue used ES6 classes, Typescript integration would be so much more smooth.

@yyx990803
Collaborator
yyx990803 commented May 4, 2016 edited

@druppy mostly it's because ES6 class in its current state is insufficient and awkward for defining components. There are no static properties, so you either have to use static get xxx () { return ... }, or attach them outside of the class declaration, or use decorators (stage 1 proposal). In reality I never extend components more than one levels deep, and always export plain object options, so I don't even use Vue.extend explicitly at all.

I personally don't use TypeScript but vue-class-component does have a d.ts file. Are you saying that it's out of sync with Vue.js core? Is there anything preventing it from working properly with TypeScript?

@druppy
druppy commented May 4, 2016

Ok, have not been using static properties directly myself, so I guess I need to look more into that before commenting on this :-) I just miss my constructor and to me it seems like we are so close to just make components classes, that extends from a VueComponent parent class.
I know there are details in Vue that shapes the current model, but I just hoped to use ES6 classes in all future code js and ts code :-)

Regarding vue-class-component, the d.ts files overlaps (but dont collide due to namespace), and it would be nice if only one vue.d.ts file was needed.

@itsFrank

Figured i'd add this here if anyone is interested, i made a library of decorators that allows you to build fully featured Vue components in standard and familiar typescript syntax. Due to the way Vue handles 'this', it works perfectly with IDEs' intellisense and I've used it along with vue-router to build a complete database admin app. I still haven't tested every corner case but it's been working really well for me. I'll be maintaining it and updating it to vue 2.0 if there's enough interest.
https://github.com/itsFrank/vue-typescript

@druppy
druppy commented Jul 11, 2016

This looks quite nice @itsFrank, I will give it a go real soon :-)

I really like the vue-class-component that Evan made, but this covers more aspects, and I too like the ability to use typescripts full potential. Vue 2.0 even makes it more exiting.

@itsFrank
itsFrank commented Jul 12, 2016 edited

Good news! I've convinced my project manager to use vue-typescript for a prototype project we are starting. This means I will be working with/on vue-typescript every day in a professional setting until at least September. This should lead to substantial feature additions and validation in the coming weeks. And obviously vue-typescript will remain open-source and free to use under the MIT license

@mdartic
mdartic commented Jul 12, 2016

great @itsFrank !

really curious to see how it will evolve :-)

@diverted247
diverted247 commented Jul 18, 2016 edited

Having looked at many different ways to integrate TypeScript and Vuejs, @itsFrank decorator system is exceptional. It restructures TS into Vue compatible js structures at compiletime while types must map to definiton files. This is really an ideal model to follow and I would like to see it become the official way Vue and TS integrate. There are a few benefits here:

  1. VueJS remains uneffected. It stays focused on the js version without needing any TS in the core project.
  2. Vue TypeScript wraps the existing Vue API and most likely trails it slightly. This is ideal given the api is very consistent (v1 to v2) but value in types can be added over it.
  3. Really the only remaining area of work is typing within templates (tsx/jsx transforms)

Great work @itsFrank!

+1 for Vue Typescript becoming the defacto way to integrate TS and VueJS.

We are actively evaluating this approach for use on an active project at Harland Clarke.

Thanks!

@amcsi
amcsi commented Jul 18, 2016

Any good way to integrate it with webpack?

@diverted247
diverted247 commented Jul 18, 2016 edited

@amcsi Look at the seed app for Vue Typescript here... Webpack integrated
https://github.com/itsFrank/vue-typescript-seed

The evaluation of the seed project really highlights how good this implementation is. Really good errors in VS Code for props/comps and workflow is aligned with how Vue runs. Only aspect there is lack of Vueify and externalized templates (html). Although we were looking to move to standalone html templates for other reasons prior, this just sped that up.

@diverted247

It would be nice to see Vue TypeScript publish sample project templates for Vue CLI

  • ts browserify
  • ts vuerouter browserify
  • ts webpack
  • ts vuerouter webpack
@amcsi
amcsi commented Jul 18, 2016

So it's not possible for this to work with .vue files? :(

@diverted247
diverted247 commented Jul 18, 2016 edited

I think it is possible but changes would need to happen in vueify (lang="ts"). TypeScript needs to compile all .ts files at the same time and mapping errors back into .vue with TS code embedded is hard. Externalizing the template and using .ts files gets you ide and ts workflow as normal (tsconfig).

Also with template external, you could process template to JS to get TS errors across templates. Typescript does this for React within the .tsx -> .jsx transform. Errors in template.

@danielschmitz
danielschmitz commented Jul 18, 2016 edited

It would be nice to see Vue TypeScript publish sample project templates for Vue CLI

ts browserify
ts vuerouter browserify
ts webpack
ts vuerouter webpack

I'm create a simple vue-cli template basead on the vue-typescript-seed:

just try:

vue init danielschmitz/vue-typescript-template myproject

@itsFrank

@diverted247 thank you, it's very motivating to hear positive feedback! I've been out of the country for the past five days so the updates have slowed down, but I'm planning on adding new features this week.

@amcsi for the .vue format; even when i was starting with vue in js, i stopped using it in favor of external templates because vscode wasn't able to provide any coding assist as there currently is no support for multi-syntax files. You had to set your editor to HTML which worked fine for highlighting, however you lost all auto-completion functions; which in the case of typescript, is half of the benefits. While i think adding lang=ts functionality to vue-loader would make it functional, you would lose one of the two main benefits of typescript (that is until IDEs start handling multi-syntax files)

@danielschmitz I just skimmed the repo but it looks solid, good stuff. I was indeed planning on making vue-cli templates in the near future.

Also, I have yet to try vue-typescript with vuex. I have never used vuex myself, but it seems like it's quite popular so it would be important to make sure they work nicely together. If someone with more experience than me could try it out and point out the issues with vuex + vue-typescript that would go a long way to making vue-typescript closer to v 1.0

@amcsi
amcsi commented Jul 18, 2016

@itsFrank WebStorm/PHPStorm could potentially support it. They don't support TS code in vue script tags yet, but you can already make use of DT stuff and use regular ES6.
This is kind of a catch-22 situation: no real reason for there to be vue file support if the editors don't support it anyway, and no real reason for the editors to support it if there's nothing to interpret it. Gotta start somewhere :P
I don't want to make demands, but this could be a really nice-to-have

@itsFrank

@amcsi yeah, however i don't think vue-typescript has the leverage yet to warrant changes on the editor's side. Take a look at this issue, if inline html scripts haven't forced them, I doubt this will.

@itsFrank
itsFrank commented Jul 18, 2016 edited

I still think having .vue support even if the editor showers you with red squiggles is something we should work towards anyways though, for small components it can be a pain to make three separate files.

@amcsi
amcsi commented Jul 18, 2016

@itsFrank I don't know about VSCode; I'm a user of Webstorm/Phpstorm
Yea like I said, I think that as it gets possible for compilers to do things, editors may then change accordingly to allow for editing those ways as well

@danielschmitz

hello @itsFrank

i will build a more complex example here:
https://github.com/danielschmitz/awesome-vue-typescript

pls wait some hours 👍

and thankyou !

@diverted247

@itsFrank There seems to be a gap in the lack of a "components" mapping object. Typically we have verbose component names and simplify them for template use using "components"

example

import { VueComponent } from 'vue-typescript'
import { SubComponent } from './components/sub/SubComponent'
import { TankComponent } from './components/tank/TankComponent'

@VueComponent({
    template: require('./battle.html')
})
export class Battle extends Vue {

    @Components({
            sub:SubComponent,
            tank:TankComponent
    })

    game:string = "Battle"

}

It might also be nice to provide a generic means to adding items into the component object. Case: API changes, new items, "components", "events", etc

Example:

import { VueComponent } from 'vue-typescript'
import { SubComp } from './components/SubComp/SubComp'
import { TankComp } from './components/TankComp/TankComp'

@VueComponent({
    template: require('./battle.html')
})
export class Battle extends Vue {

    @ComponentObject( "components" , {
            sub:SubComp,
            tank:TankComp
    })

    game:string = "Battle"

}
@itsFrank
itsFrank commented Jul 19, 2016 edited

@diverted247 For this case, I think the current behavior of VueComponent is sufficient

example:

import { VueComponent } from 'vue-typescript'
import { SubComp } from './components/SubComp/SubComp'
import { TankComp } from './components/TankComp/TankComp'

@VueComponent({
    template: require('./battle.html'),
    components: {
            sub:SubComp,
            tank:TankComp
    }
})
export class Battle extends Vue {

    game:string = "Battle"

}

VueComponent allows you to use the entire component api in the decorator if vue-typescript is trailing. I think that decorators should only be created for properties that will be referenced in code. In this case, the contents of the "components" object will never be referenced inside the class, so typescript doesn't have to know about it.

@itsFrank
itsFrank commented Jul 19, 2016 edited

For anyone reading this issue in the future, something like this is actually perfectly valid:

import { VueComponent } from 'vue-typescript'

@VueComponent('my-component', {
    data: {
        var1: 'hello',
        var2: 'goodbye'
    },
    computed: {
        confusedGreeting: function(){
            return this.var1 + ' ' + this.var2
        }
    },
    watch: {
        var1: function(new, old) {
            console.log(old + ' became ' + new)'
        }
    }
})
export class UselessClass {}

In the above case, adding <my-component></my-component> in your html would instantiate the above component just like in standard vuejs.

So if vue-typescript is missing any features, they can be passed into the decorator. And if you have to pass values that will be used in code inside the decorator, simply cast 'this' to any like so:

(<any>this).valueInDecorator

It's ugly, but it will work until vue-typescript gets updated.
Just like Typescript is a superset of javascript (in that you dont lose any features) vue-typescript is sort of built with this mentality as well (except for things outside of typescripts control like vueify)

@diverted247

Digging into this further...

Ok so you are keeping the @VueComponent object generic if an object is passed. +1

Taking a deeper look at output. It looks like TS is injecting methods __decorator and __metadata to do all this at runtime. See
screenshot 2016-07-19 09 28 17

So the overhead of this is transforming the data structures at runtime during component creation.
unspecified

I had thought TS compiler was doing this at compiletime not at runtime. Makes me think about this differently.

Another item is that TypeScript cannot see types across methods and instances as invalid. Here I am mistyping a string as number and TS caught the error in check() but missed the ready() error. Essentially the @VueComponent object is not type checked or scoped to class.
unspecified-2

Please do not take this the wrong way, I am just digging in here to understand how this works.

@itsFrank

@diverted247 Yes, there is a small overhead , mainly iterating over keys and constructing the component object at loadtime since VueComponent is evaluated when the file is loaded.

This overhead will have no effect once the components are loaded since at that point they are already constructed and it's all pure vuejs. I include a utility in vue-typescript to measure the %time impact of vue-typescript vs the total load time (you'll have to look into the source ts as i don't plan on documenting it), and even on a medium scale project, it is negligible when compared to vue's loadtime. You would need to create components with multiple thousands of individual variables and functions for it to have an effect as far as i can tell.

As for type-checking with the VueComponent object, there really isn't any way of doing this since the object and component class are not merged prior to loadtime.

My philosophy is that you should be using the decorators and class behaviors of VueComponent as much as possible, and only use the object when there is no option provided by vue-typescript.

Ill post some output from the timing utility shortly

@itsFrank
itsFrank commented Jul 19, 2016 edited

This is the output for a medium size project with 25 components:

vue-typescript preformance impact:
    total load time: 914
    vue-typescript computation time: 29
    percentage impact: 3.1728665207877462%

times are in ms
Note this project uses vue-router, loader, resource, i18n, touch plus bootstrap jquery and threejs

@dyu
dyu commented Sep 3, 2016

I've been following this thread for a while as I was looking to convert my personal vue 0.10 + gwt toolkit to typescript 2 and vue 2. @gamperl's initial protoype was such a great help.

With typescript 2.0's features, you do not have to decorate every class to make it a component (too heavy weight).
Instead you can code like es6/es2015 with no extra runtime overhead / code generated using this feature where you can specify the type of this for functions

interface MyModel {
     msg: string
}

export default {
    name: 'Foo', // specify the component name
    data(): MyModel {
        return {
            msg: 'hello'
        }
    },
    methods: {
        append(this: MyModel, suffix: string) {
            this.msg += suffix
        }
    },
    computed: {
        upper_msg(this: MyModel) {
             return this.msg.toUpperCase()
        }
    },
    template: `<div @click="append('!')">{{ msg }} | {{ upper_msg }}</div>`
}

You get all the intellisense with this paradigm without the overhead of decorators.

If you happen to use typescript 2.0 and use inheritance in your typescript-based components, take a look at vuets (disclaimer: I'm the author)

@gamperl
gamperl commented Sep 6, 2016

@dyu this is a nice idea, without decorators the code gets much simpler, but you loose the intellisense on methods and hooks:

interface MyModel {
     msg: string
}

export default {
    name: 'Foo', // specify the component name
    data(): MyModel {
        return {
            msg: 'hello'
        }
    },
    methods: {
        append(this: MyModel, suffix: string) {
            this.msg += suffix
        },
        append2(this: MyModel, suffix: string) {
            this.append(suffix); // this shows an error, since MyModel has no methods
        },
    },
    template: `<div @click="append('!')">{{ msg }} | {{ upper_msg }}</div>`
}

Do you have an idea on how to fix this?

@druppy
druppy commented Sep 6, 2016

Could MyModel be used together with vuejs.Vue to form the Self class ?

interface MyModel {
     msg: string
}

interface MyModelSelf extends ModelMsg, vuejs.Vue {
}

export default {
   data() : MyModel { 
      return {
         msg: 'hello'
      }
   }
   methods: {
      append( this: MyModelSelf, suffix: string ) {
         ...
      }
   }
}

It is readable but a bit verbose :-)

@dyu
dyu commented Sep 9, 2016

@gamperl Sure. This will remove the errors.

export interface MyModel {
     msg: string
     append(this: MyModel, msg: string)
}

export default {
    methods: {
        append(this: MyModel, suffix: string) {
            this.msg += suffix
        },
        append2(this: MyModel, suffix: string) {
            this.append(suffix)
        }
    }
}

@druppy Yep that works as well. It appears verbose sure. I uses classes without decorators for complex components using similar approach in vuets.

@aloisdg
aloisdg commented Sep 22, 2016

Hello,

After reading all of this, I feel the need of One True Vue.ts. I like Vue.js as it is, but I would love an "official" Vue.ts project. I discover a lot of good way to use TypeScript with Vue here and I am looking to use @itsFrank's one. I will dig it a bit before. Would it be possible to see a merge between this one and @dyu 's one? (I like the idea of an org and great idea for the logo!). Also if a One True community drive project rised, @yyx990803 could you add it to vuejs' readme?

There is a lot of good will here. Thats nice 😄

@druppy
druppy commented Sep 29, 2016

@aloisdg I think that the current way things are going, where the d.ts files becomes part of the npm and maintained by the Vue team, is as ideal as possible. This way there will be an official way to support typescript in Vue and we can focus on expanding on that foundation.

@kaorun343
Contributor

When I was trying Angular 2, I found this package ts-helpers.
This package enable us to reduce file size when using decorators.

@yyx990803
Collaborator

Closing now that vue, vue-router and vuex 2.0 all ship with typings right in their npm packages. In terms of component decorators, we have the offical vue-class-component and many great community solutions. Thanks to everyone involved in this discussion!

@yyx990803 yyx990803 closed this Oct 1, 2016
@amcsi
amcsi commented Oct 1, 2016

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.

@ktsn
Member
ktsn commented Oct 1, 2016

@amcsi There is vue-ts-loader to use TypeScript in single file component.

@amcsi
amcsi commented Oct 1, 2016

Oh wow!

@HerringtonDarkholme
Contributor

There is also an introductory guide for Vue-TS integration. Check it out!

@ansien12
ansien12 commented Oct 8, 2016 edited

Made a Vue 2 + Typescript 2 example using standalone vue.

https://github.com/Ansien12/vue2-typescript2-example

I have very little experience with vue/ts/webpack, so feel free to make a pull request.

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.

@HerringtonDarkholme
Contributor

@Ansien12 would you please file bugs on related projects? I'm curious about them.

@octref
octref commented Nov 6, 2016

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 props for this.)?

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

  • Type in Vuex store is great
  • I never found myself needing much Type in Vue Component, as it's just hooking up data and actions/getters from store to the template.

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.

@druppy
druppy commented Nov 6, 2016 edited

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 constructor back, it could all become very beatiful.

So, maybe what would help (correct med if I am wrong), is to have a few vue-cli templates like, that could show how to boot up a project using:

  • vue-ts-loader using vue.ts files (maybe it merge into ts-loader ?)
  • using av-ts both within vue files and vanilla ts, or just use the vue-class-component

As far as I understand it, the biggest unresolved issue is that we can only use tsx file via tsc->babel->js, as tsc only support pass through or React.

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.

@SeanJM
SeanJM commented Nov 7, 2016

@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

@HerringtonDarkholme
Contributor

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.

@octref
octref commented Nov 11, 2016 edited

@HerringtonDarkholme Would you mind sharing a screenshot for VSCode?

@HerringtonDarkholme
Contributor
HerringtonDarkholme commented Nov 11, 2016 edited

Vim:
screen shot 2016-11-11 at 1 22 15 pm

VSCode:

screen shot 2016-11-11 at 1 23 35 pm

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 openFileCommand to service.

@octref
octref commented Nov 11, 2016

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.

@druppy
druppy commented Nov 11, 2016

@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 --jsxFactory feature in TS will bring more focus on this. Being able to use 3 different code models in Vue, having really good performance and low footprint really makes Vue a solid choice.

@SeanJM
SeanJM commented Nov 15, 2016 edited

@druppy I debugged it and posted a working configuration as a gist here: https://gist.github.com/SeanJM/263f9dda94ed6e9bf4323bd0b136de73

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment