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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(types): expose ElementAttributesProperty for TSX #9379

Closed

Conversation

@andoshin11
Copy link

@andoshin11 andoshin11 commented Jan 27, 2019

What kind of change does this PR introduce? (check at least one)

  • Bugfix
  • Feature
  • Code style update
  • Refactor
  • Build-related changes
  • Other, please describe:

Does this PR introduce a breaking change? (check one)

  • Yes
  • No

If yes, please describe the impact and migration path for existing applications:

The PR fulfills these requirements:

If adding a new feature, the PR's description includes:

  • A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

Descriptions

With current type definitions, it's extremely difficult for developers to pass props to children components when writing TSX since there's no exposed property that JSX can handle as element attributes properties.

2019-01-27 22 45 39

This PullRequest achieves 2 things.

  • Creates new property _attrs to the ExtendedVue type so it can be used inside JSX.ElementAttributesProperty.(Examples are below)
  • Transform non-required props into optional properties of props interface.

Example

Given these 2 children components...

// PrimaryButton.tsx
import Vue from 'vue'

export default Vue.extend({
  name: 'Primary Button',
  props: {
    label: {
      type: String,
      required: true as true
    },
    color: String
  },
  computed: {
    style(): string {
      return `color: ${this.color || 'blue'};`
    }
  },
  render() {
    return <button style={this.style}>{this.label}</button>
  }
})
// SecondaryButton.tsx
import Vue from 'vue'

export default Vue.extend({
  name: 'Secondary Button',
  props: ['color', 'label'],
  computed: {
    style(): string {
      return `color: ${this.color || 'blue'};`
    }
  },
  render() {
    return <button style={this.style}>{this.label}</button>
  }
})

and prepare shims-tsx.d.ts like this

// shims-tsx.d.ts
import Vue, { VNode } from 'vue'

declare global {
  namespace JSX {
    interface Element extends VNode {}
    interface ElementClass extends Vue {}
    interface ElementAttributesProperty {
      _attrs: any
    }
    interface IntrinsicElements {
      [elem: string]: any
    }
  }
}

Property completion works as expected.

2019-01-27 22 55 58

Type error warned as expected.

2019-01-27 22 56 15

and no more errors with correct props declaration 馃憤

2019-01-27 23 00 09

@andoshin11 andoshin11 force-pushed the andoshin11:feature/extract-outer-props-type branch to 9a38c4f Jan 27, 2019
@andoshin11
Copy link
Author

@andoshin11 andoshin11 commented Jan 27, 2019

oops... fixing errors

@andoshin11 andoshin11 mentioned this pull request Jan 27, 2019
1 of 7 tasks complete
@ktsn
Copy link
Member

@ktsn ktsn commented Feb 7, 2019

Thanks for your amazing work! I briefly looked into it and it would be so useful for TSX users!
Only thing I'm concerning is that it will make type parameters of component more complicated. I'm not sure if we can directly declare the required/optional info into Props type parameter but I think it is ideal. I'll take a look if we can simplify the type declaration more.

As a side note, in Vue v3, we can declare Props type by hand. So we may include required/optional info in Props type directly.

@skyrpex
Copy link

@skyrpex skyrpex commented Mar 21, 2019

Any chance of this working along with https://github.com/kaorun343/vue-property-decorator? It's the only way I found to enable typehinting and autocompletion in my editor.

@skyrpex
Copy link

@skyrpex skyrpex commented Mar 21, 2019

Maybe we can't use the @Prop decorator but use some sort of Vue.extend to define the props and then make the class component extend it (something similar to what React users need to do).

import { Vue, Component, Prop } from 'vue-property-decorator'

const YourComponentProps = Vue.props({
    propA: Number,
    propB: { type: String, default: 'default value' },
    propC: [String, Boolean],
});

@Component
export default class YourComponent extends Vue<YourComponentProps> {
    get text() {
        return `${this.propA} ${this.propB} ${this.propC}`;
    }
}
baocancode added a commit to webokio/webok that referenced this pull request Apr 5, 2019
Some benefits:
- Better editor and tooling support
- No need for `h: CreateElement` in any `render()`
- Can format/lint the code
- In the future, can remove usage of `components` if vuejs/vue#9379 is merged
- Use single css classes (copied from tachyons) to style components, since most of the styling can be done with Vuetify, also remove `sass` and `sass-loader`
@mbostwick
Copy link

@mbostwick mbostwick commented Sep 30, 2019

@baocancode did you see the conflicting file blocking the automated checks?

@andoshin11
Copy link
Author

@andoshin11 andoshin11 commented Oct 17, 2019

I left this PR wondering for too much time. I'll close this until Vue 3 comes along.
Thx for all of your feedbacks! much appreciated :)

@andoshin11 andoshin11 closed this Oct 17, 2019
2.7 automation moved this from To do to Done Oct 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
2.7
  
Done
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants