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

Typings for $refs should also include Component | Component[] #9854

Closed
terrymun opened this Issue Apr 10, 2019 · 6 comments

Comments

Projects
None yet
5 participants
@terrymun
Copy link

terrymun commented Apr 10, 2019

Version

2.6.10

Reproduction link

https://codesandbox.io/s/p7krpry9vm

Steps to reproduce

  1. Assign a component a ref attribute, say, <my-component ref="myComponent" />
  2. Import the typings for component from vue, i.e. import { Component as VueComponent } from 'vue'; (the aliasing is needed because I am also using vue-property-decorator's Component module, but that is not relevant to the question)
  3. Declare the types for $refs when composing a component, i.e. public readonly $refs!: { myComponent: VueComponent }

What is expected?

I expect the Component type to be accepted in the $refs definition.

What is actually happening?

I get a message that the type of this.$refs.myComponent is incompatible with the pre-existing type declared for this.$refs.<key>.

Here is a screenshot of the actual error I am getting in production code:

Code_2019-04-10_09-16-25


This issue came across because I need to access a nested element within a Vue component when writing in TypeScript. In native JS, I can simply query the DOM of the Vue component using this.$refs.myComponent.$el.querySelector(...) without an issue. However, in TypeScript, I get a warning because I need to pre-declare the typings for $refs at the top of the component, i.e.:

public readonly $refs!: {
  myComponent: VueComponent
}

When you log this.$refs.myComponent when the parent/consuming component is mounted to the console, you will see that it returns a Vue component instance. This is incompatible with the pre-existing typings for $refs, which only allows the following types: Vue | Element | Vue[] | Element[].

I propose that the typings for $refs by extended to:

{ [key: string]: Vue | Element | Component | Vue[] | Element[] | Component[] }
@underfin

This comment has been minimized.

Copy link

underfin commented Apr 10, 2019

I think its rigorous, public readonly $refs!: { myComponent: MyComponent }

@terrymun

This comment has been minimized.

Copy link
Author

terrymun commented Apr 10, 2019

@underfin That will work, but only in cases where the ref actually points to an actual named component (which is my case, so your suggestion works 100% for me) 👍 however, what if somebody has this in their app?

<component
  v-bind:is="componentToUse"
  v-bind:-ref="myComponent" />

In this case, we can't know the actual component that will be used in place, and therefore have to use a generic VueComponent type of the reference.

@underfin

This comment has been minimized.

Copy link

underfin commented Apr 10, 2019

@terrymun
@Component({ name: 'MyComponent' })
export default class MyComponent extends Vue { }
MyComponent is extends Vue, so can use $refs!: { myComponent: Vue } with generic type.

@HerringtonDarkholme

This comment has been minimized.

Copy link
Member

HerringtonDarkholme commented Apr 15, 2019

I believe $refs contains either dom element(s) or component instance(s). Component in Vue's typing is actually the component configuration object or component class, not the component instance itself.

You typing should be $refs: { myComponent: Vue} IMHO

@KaelWD

This comment has been minimized.

Copy link
Contributor

KaelWD commented Apr 18, 2019

☝️

myComponent: Vue or myComponent: InstanceType<typeof MyComponent>

@terrymun

This comment has been minimized.

Copy link
Author

terrymun commented Apr 18, 2019

Thanks for all your help! I've learned that:

  • If the component is defined already, we can just assign its own class as its type, e.g. myComponent: MyButtonComponent if I'm importing it as import MyButtonComponent from <...>;
  • If the component is indeterminate, assigning it a generic type of Vue works

@terrymun terrymun closed this Apr 18, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.