Converting Vue 3 refs to different types using instanceof in Typescript

When working with Vue using the Options API, here is a code snippet I have:

<script lang="ts">
import * as THREE from 'three';

export default {
    mounted() {
        console.assert(this.$refs.container instanceof HTMLCanvasElement, this.$refs.container);
        const renderer = new THREE.WebGLRenderer({
            canvas: this.$refs.container as HTMLCanvasElement,
            antialias: true,
            alpha: true
        });
        
    }
};
</script>

<template>
    <canvas ref="container" id="earthCanvas"></canvas>
</template>

Transitioning to the Composition API poses a challenge. The call to "this" no longer works correctly, as it's now considered "possibly undefined". To resolve this issue, I opted for using 'ref' and 'container.value' instead:

<script lang="ts">
import * as THREE from 'three';
import { onMounted, ref } from 'vue';

let container = ref(null)
onMounted(() => {
    console.assert(container.value instanceof HTMLCanvasElement, container.value);
    const renderer = new THREE.WebGLRenderer({
        canvas: container.value as HTMLCanvasElement,
        antialias: true,
        alpha: true
    });

});
</script>

<template>
    <canvas ref="container" id="earthCanvas"></canvas>
</template>

However, Vue throws an error with the implementation: Calling 'container.value' results in: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter".

I'm still learning, so your guidance on how to appropriately convert a ref to the element would be greatly appreciated. Apologies for the basic question...

Even chatGPT couldn't help me pinpoint what I might be missing. Using its suggestions lead to more errors... https://i.sstatic.net/65N6M.png

Answer №1

The container value in question is of type Ref<null>, indicating that it is a reference to a null value. Typescript interprets this as being strictly of type null.

To specify the specific type that your reference should be, you need to utilize generic parameters:

const container = ref<HTMLCanvasElement | null>(null);

By properly assigning types, your use of instanceof will function correctly.

Answer №2

Instead of using assert, a better approach could be to implement a conditional check to verify if ref is null:

let element = ref<HTMLCanvasElement | null>(null)
onMounted(() => {
  if (element.value) {
    const renderer = new THREE.WebGLRenderer({
        canvas: element.value,
        antialias: true,
        alpha: true
    });
  }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Observable task queuing

Here's the scenario: In my application, the user can tap a button to trigger a task that takes 2 seconds to complete. I want to set up a queue to run these tasks one after another, in sequence. I am working with Ionic 3 and TypeScript. What would be ...

What is the best way to apply ngClass to style a JSON object based on its length?

Currently, I am working with a mat-table that displays data from a JSON object. My goal is to filter out all records with an ID of length 5 and then style them using ngClass in my HTML template. How can I achieve this? Below is the code I am working with: ...

The v-for directive does not automatically update components in real time

I created a main component called Data, which retrieves state from Vuex. I then use this state to create multiple child components called Table. These child components receive some of the Vuex data as props, all within a v-for loop. <template> < ...

Obtain a compilation of files that have been successfully uploaded using vue-uploader

Is there a way for me to retrieve an array of successfully uploaded files when using the vue-uploader component? Visit the Vue-Uploader Github page I am interested in achieving something similar to the following: <template> <uploader :options ...

"Utilize the createReducer function with builder syntax to handle callbacks

Having trouble using createReducer with the builder syntax to update the auth state based on user login success or failure. Running into TS2769 error specifically in the second builder.addCase where adjusting the state for failed logins. Seeking assistance ...

Best practices for managing multiple checkboxes with identical v-model in vue.js

Could someone please assist me with the process of sending and retrieving multiple checkbox values from vue.js to the backend? I have been searching the internet for guidance on this topic, but with limited success. Here's the scenario: I have a cate ...

There is no correlationId found within the realm of node.js

Currently, I am in the process of implementing correlationId functionality using express-correlation-id. I am diligently following the guidelines provided on this page: https://www.npmjs.com/package/express-correlation-id. I have successfully imported the ...

Error: Module is undefined in the Vue project

After creating a new Vue app using npm init vue@latest as outlined in the official documentation, I attempted to integrate Tailwind CSS by following the instructions in the Vue & Vite guide on their website. However, upon inspecting the tailwind.config ...

What is the best way to access the data stored within a Promise object in a React application?

Below is the snippet of my code that handles parsing application data: async function parseApplication(data: Application) { const fieldGroupValues = {}; for (const group of Object.keys(data.mappedFieldGroupValues)) { const groupValue = data.mappedF ...

Is there a way to address the sporadic behavior of rxjs combineLatest when used in conjunction with ReplaySubject

My current struggle lies within this particular example: const r1 = new ReplaySubject(2); const r2 = new ReplaySubject(2); r1.next('r1.1'); r1.next('r1.2'); r2.next('r2.1'); combineLatest([r1, r2]).subscribe(console.log); // ...

Angular: ensure the form reverts to its initial value when the modal is closed and reopened

I am facing an issue with my items section. When I click on an item, a modal window opens allowing me to edit the text inside a textarea. However, if I make changes to the text and then cancel or close the modal, upon reopening it, the previously modified ...

The request to search for "aq" on localhost at port 8100 using Ionic 2 resulted in a 404 error, indicating that the

Trying to create a basic app that utilizes an http request, but facing challenges with cors in ionic 2. To begin with, modifications were made to the ionic.config.json { "name": "weatherapp", "app_id": "", "v2": true, "typescript": true, "prox ...

In the Vue mounted hook, the term "TradingView" has not been declared

I am unsure if this is the right place to ask this question, but I am currently using the tradingview library. While it is working for me, it is not functioning the way I intend it to. As per the documentation, I have placed my code in the index.html file ...

Having trouble utilizing HTML Canvas in the newest release of Angular and TypeScript

After extensive searching on the internet, I have not been able to find any working examples of using HTML canvas in Angular. It seems that changes in syntax in Typescript and Angular's newer versions have rendered all existing solutions obsolete. I ...

Showing error messages in Angular when a form is submitted and found to be invalid

My form currently displays an error message under each field if left empty or invalid. However, I want to customize the behavior of the submit button when the form is invalid. <form #projectForm="ngForm" (ngSubmit)="onSubmit()"> ...

Can html-webpack-plugin be configured to create <style> elements from CSS files?

I am managing a static site with Vue and Webpack. In my project, I have a file named style.css containing global CSS rules which I import using import './styles.css' in my index.js file. Additionally, I have some .vue files that generate their o ...

Retaining filter values when using the Vue.js history back button

Recently, I've been given a project to work on that involves using Vue.js (I'm pretty new to Vue) The project includes creating a page that displays items based on filters set by the user. The user selects the filters and the listing page update ...

What is the most efficient method for examining dependencies in Yarn 2 (berry)?

Is there a way to check for vulnerabilities in Yarn 2 dependencies? In Yarn 1.x, you could run yarn audit, similar to npm audit. However, this command is not available in Yarn 2. According to this issue on the Yarn berry Github, it may not be implemented ( ...

Create personalized CustomElements in real-time

I developed a helper function to dynamically set up all CustomElements: let moduleDefaults = new Map(); let customElementsMap = new Map(); const registerComponents = () => { // ^ Check for .ce files -> then register components for (const [ke ...

Tips for utilizing window.scrollTo in order to scroll inside an element:

I'm experiencing an issue where I have a vertical scrollbar for the entire page, and within that, there's an element (let's call it 'content') with a max-height and overflow-y scroll. The 'content' element contains child ...