Hi all, thanks in advance for any guidance. I'm new to TypeScript.

The above error should not exist, because this.$refs.<name> can be an instance of Vue or of Element.
Element extends Node, and Node does indeed have appendChild<T extends Node>(newChild: T): T; defined in its TypeScript Declaration File.
You can see that the error appears to be generated because TS is incorrectly assuming this is an instance of Vue and not an instance of Element - why is this? Shouldn't it see that it might be an Element and not give an error?
I'm pretty confident that my environment is set up correctly, I have all node type files loaded.
Thanks again for your guidance. Despite TS complaining, this code does compile and run just fine. The complaint is annoying though.
Wow... I literally have not changed anything, and now instead of assuming it's a Vue instance, it's assuming it's an array of Element instances:

Does anyone have any ideas?
Incorrect solution that I tried 1:
If I edit this line in the Vue type declarations to read:
readonly $refs: { [key: string]: Element};
...the error goes away. Something seems very wrong to me about all this.
Incorrect solution that I tried 2:
If I change the line in the screenshot to read:
(this.$refs.canvases as Element).appendChild(gameScreen.getView());
...the error goes away. But that shouldn't be necessary, should it?
@JVMartin
Hi.
You can do like this below.
@Component
class Game extends Vue {
// please add these codes into yours
$refs: {
canvases: HTMLElement
}
mounted () {
this.$refs.canvases.appendChild(gameScreen.getView())
}
}
Vue's typings include all possible type as the union type.
You should manually annotate your $ref with expected type as @kaorun343 suggested.
Awesome - thank you @kaorun343 and @ktsn for your help!
This no longer works today (with the latest version of Vue & vue-cli 3). @kaorun343 @ktsn Any ideas
https://github.com/vuejs/vue-class-component/issues/94#issuecomment-408224406
@ffxsam
@Component
class Game extends Vue {
// please add these codes into yours
$refs!: { // <- "!" is needed
canvases: HTMLElement
}
mounted () {
this.$refs.canvases.appendChild(gameScreen.getView())
}
}
@kaorun343 Wow! You rock! Thank you so much. I would've never figured this out. I'm not familiar with the ! - what's that all about?
And is it possible to define ref types in standard SFC (non-class) format?
documentation about ! is here
is it possible to define ref types in standard SFC (non-class) format?
import Vue, { VueConstructor } from "vue";
export default (Vue as VueConstructor<Vue & { $refs: { canvases: HTMLElement } }>).extend({
// ...
})
@wonderful-panda Awesome! The only thing I'm not able to do with SFCs is use a component as a type. E.g.:
import DataTable from '../components/shared/DataTable.vue'; // exports Vue.extend()
export default (Vue as VueConstructor<
Vue & { $refs: { dataTable: DataTable } }
>).extend({
It underlines "DataTable" and says "Cannot find name 'DataTable'." However, if I switch to class-based components, it works great:
import DataTable from '../components/shared/DataTable.vue'; // export class
@Component
export default class MyComponent extends Vue {
$refs!: {
dataTable: DataTable;
}
@ffxsam If you use TypeScript 2.8 or later, try
$refs: { dataTable: InstanceType<typeof DataTable> }
@wonderful-panda Ugh, I didn't know about that because it's not in the TypeScript documentation. Thanks, I'll try it tomorrow.
@wonderful-panda You are indeed a wonderful panda. :grin: Thank you!
Most helpful comment
documentation about
!is here