Skip to content
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

Further improve Vue type declarations for canonical usage #6391

Merged
merged 56 commits into from
Oct 6, 2017

Conversation

HerringtonDarkholme
Copy link
Member

@HerringtonDarkholme HerringtonDarkholme commented Aug 17, 2017

This pull request supersedes #5887 .

Key improvements:

  1. More backward compatible via generic default
  2. Props type inference

@ktsn @kaorun343 @DanielRosenwasser Your reviews or suggestions are welcome!


This section provides more background for other reviewers/readers.

Vue + TS users currently need helper library like vue-component-class to provide alternative API for TypeScript. Alternative API uses code pattern that TypeScript recognizes, but it splits Vue community.

Thankfully, TypeScript introduces ThisType which can greatly improve Vue's canonical API. This PR introduces ThisType to Vue's official typing.

More importantly, this improvement also benefits JavaScript users! VSCode users or Vue-language-server users exploits TypeScript compiler to provide editor services for JavaScript. Thus the typing improvement can help JavaScript completion more intelligent.

Goal:

  1. Provide good enough completions for both JS users and new TS users (if they use canonical API).
  2. Don't break existing TS libraries or projects. Or, make breaking minimal.

Non Goal:

  1. This PR won't provide 100% typing precision or use case coverage. Such typing would be too prohibitive for both maintainers and users to reason.
  2. Checking errors in JS isn't kept in mind. So changing existing JS to TS will cause errors.

Known limitations:

  1. new Vue() wouldn't return a type with props type. This is caused by compiler limitations.
  2. Props typing uses a hacky trick.
  3. returning properties on this might trigger cyclic error, manual annotation is needed.
  4. Prop type's union type declaration like oneProp: [String, User] might not work without manual annotation.

Next step:
Since we already has a canonical Vue API in TS, next we can ship tsx support in the official repo.

yyx990803 and others added 30 commits February 26, 2017 18:23
… as members from 'data' and the Vue instance.
Conflicts:
	types/options.d.ts
	types/test/options-test.ts
	types/test/vue-test.ts
	types/vue.d.ts
* build(release weex): ignore the file path of entries

* [release] weex-vue-framework@2.4.2-weex.1
Simplify 'CreateElement', remove potential error in 'AsyncComponent' …
@vuejs vuejs deleted a comment from RekcuFrehtom Sep 14, 2017
@yyx990803
Copy link
Member

@HerringtonDarkholme are you on slack? Can you give an email address so I can invite you to the team slack? (maybe via Twitter DM)

@yyx990803
Copy link
Member

I drafted a blog post regarding the 2.5 TS upgrade, feedback needed!

https://medium.com/the-vue-point/upcoming-typescript-changes-in-vue-2-5-e9bd7e2ecf08

/cc @HerringtonDarkholme @DanielRosenwasser @ktsn @octref

@robert-claypool
Copy link

@yyx990803, looks good, two typos:

  • "Daniel Rosenwasser from the TypeScript started" --> missing word?
  • "in anyway; per semver" --> any way

@yyx990803
Copy link
Member

@robert-claypool thanks, fixed.

@HerringtonDarkholme
Copy link
Member Author

@yyx990803 I'm already on slack!

@DanielRosenwasser
Copy link

I will try to give some deeper feedback later, but

  • "So that we" doesn't flow will into the items listed
  • The features we added that enabled this support were chiefly in 2.1 to 2.3.

extend<PropNames extends string = never>(definition: FunctionalComponentOptions<Record<PropNames, any>, PropNames[]>): ExtendedVue<V, {}, {}, {}, Record<PropNames, any>>;
extend<Props>(definition: FunctionalComponentOptions<Props, RecordPropsDefinition<Props>>): ExtendedVue<V, {}, {}, {}, Props>;
extend<Data, Methods, Computed, PropNames extends string>(options?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): ExtendedVue<V, Data, Methods, Computed, Record<PropNames, any>>;
extend<Data, Methods, Computed, Props>(options?: ThisTypedComponentOptionsWithRecordProps<V, Data, Methods, Computed, Props>): ExtendedVue<V, Data, Methods, Computed, Props>;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having tried this out, while Props inference is great, I think there will be cases where someone will want to write an interface for props and then let Data, Methods, and Computed be inferred on their own, and then let

Maybe we should reorder this so that Props comes first? something like

extend<Props = Record<PropNames, any>, PropNames extends string = never, Data = {}, Methods = {}, Computed = {}>(options?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): ExtendedVue<V, Data, Methods, Computed, Props>;
extend<Props = {}, Data = {}, Methods = {}, Computed = {}>(options?: ThisTypedComponentOptionsWithRecordProps<V, Data, Methods, Computed, Props>): ExtendedVue<V, Data, Methods, Computed, Props>;

What do you think @HerringtonDarkholme?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if inferring default generic parameter is available in current TS. microsoft/TypeScript#14400 or this comment microsoft/TypeScript#13487 (comment)

So users have to annotate all the type parameters as long as they want to specify at least one parameter.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we haven't yet implemented that. This isn't a blocker though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm merging this in preparation for 2.5 release. We can improve upon this in a separate PR later.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were using this pattern below

interface AppComponent extends Store, Vue {
  // Additional typed props besides ones defined on Store here
}

export default {
// ...
} as ComponentOptions<AppComponent>

but it looks like this isn't possible with Vue 2.5 no more. Is there another way to type your props now? Possible workaround is to wrap props inside computed property with added type, but this isn't really elegant.

@eshimischi
Copy link

@yyx990803 @HerringtonDarkholme @DanielRosenwasser any changes to Vue typings due to TS 2.6 release?

@DanielRosenwasser
Copy link

@eshimischi if you're having any specific problems with the type declarations given TypeScript 2.6, I'd suggest you file a separate issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants