Accessing a property that doesn't exist on a union type in Phaser using TypeScript

Currently, I've been immersed in the world of game development with Phaser 3 by following this insightful tutorial at . However, my focus has now shifted towards deploying these games online and adapting the code for use with TypeScript while gearing up to integrate it into an Ionic 5 app. In the tutorial, a crucial part involves setting the velocity of a player sprite. To accomplish this, two essential classes need to be created: Entities.js (renamed as entities.ts) and Player.js (transformed into player.ts). These entities are designed to extend Phaser.GameObjects.Sprite, with the player being an entity that extends the entities class. Although everything is progressing smoothly, an issue arises when attempting to set the player's velocity.

The first file is my entities.ts:

class Entity extends Phaser.GameObjects.Sprite {
  constructor(scene, x, y, key, type) {
    super(scene, x, y, key);

    this.scene = scene;
    this.scene.add.existing(this);
    this.scene.physics.world.enableBody(this, 0);
    this.setData('type', type);
    this.setData('isDead', false);
  }
}

Next, we have my player.ts:

class Player extends Entity {
  constructor(scene, x, y, key) {
    super(scene, x, y, key, 'Player');

    this.setData('speed', 200);
    this.play('sprPlayer');
  }

  moveUp() {
    this.body.velocity.y = -this.getData('speed');
  }

  moveDown() {
    this.body.velocity.y = this.getData('speed');
  }

  moveLeft() {
    this.body.velocity.x = -this.getData('speed');
  }

  moveRight() {
    this.body.velocity.x = this.getData('speed');
  }

  update() {
    this.body.setVelocity(0, 0);
  }
}

Upon introducing the line this.body.setVelocity(0, 0), an error surfaces:

Property 'setVelocity' does not exist on type 'Body | StaticBody | BodyType'. Property 'setVelocity' does not exist on type 'StaticBody'
. It appears that the sprite's body can be classified as either a Body, StaticBody, or BodyType object. The documentation reveals that the Body class supports the function
setVelocity</code, whereas the <code>StaticBody
class lacks this ability.

Could it be that TypeScript expects all types within the union to support the function? If so, is there a way to specify the specific body type being used in function calls? Despite multiple attempts, parsing doesn't seem to yield any solutions.

In contemplating whether transitioning to developing in plain JavaScript for Ionic may alleviate the issue, I stumbled upon resources like . Nevertheless, before considering such a change, is there a method to explicitly define the desired type from the union for my function calls? Your insights would be greatly appreciated. Thank you for your assistance.

Answer №1

The error message is informing you that the player body in question is one of 'Body', 'StaticBody', or 'BodyType'. However, StaticBody does not contain a method called setVelocity. To address this issue in Typescript, you can utilize typeguards when dealing with union types that have distinct properties.

To resolve this, you need to verify if the body has a setVolicity function available.

update() {
    // By checking for "setVelocity", Typescript can determine it's not a StaticBody
    if ("setVelocity" in this.body)
    this.body.setVelocity(0, 0);
  }

Alternatively, you can create a custom typeguard function and employ it within the if statement like so:

// Custom typeguard function returning 'body is Body'    
function isBody(body: Body | StaticBody): body is Body {
  return (body as Body).setVelocity !== undefined;
}

if (isBody(this.body)) {
  this.body.setVelocity(5); 
}

Answer №2

Per jcalz's explanation, the solution involved testing whether the object in question is a part of the class which holds the function that needs to be utilized. Simply put, it was important to confirm our intention to use Body rather than StaticBody. This verification could have been carried out by checking if the function exists within the object:

if('setVelocity' in this.body) {
  this.body.setVelocity(0, 0);
}

Furthermore, we could have validated if the object aligns with the expected instance, like so:

if(this.body instanceof Phaser.Physics.Arcade.Body) {
  this.body.setVelocity(0, 0);
}

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

What is the reason for the base class constructor not being able to access the property values of the derived class

Recently, I came across this scenario in my code: class Base { // Default value myColor = 'blue'; constructor() { console.log(this.myColor); } } class Derived extends Base { myColor = 'red'; } // Prints ...

Ways to recycle the output of the three.js fragment shader

Recently delving into GLSL shaders in three.js, I am currently experimenting with creating a simple and efficient blur effect on a mesh texture. Below is the fragment shader code I have been working on: void blurh(in vec4 inh, out vec4 outh, int r) { ...

"Troubleshooting JQuery: Dealing with Errors in Ajax Get

I'm attempting to make a call to a PHP script using a GET request and passing the data theaddress, but the results are displaying the source code of the page I'm trying to call. The page I'm trying to call can be found here. Here is my AJAX ...

Communication between a directive controller and a service via an HTTP call

I'm currently developing an Angular directive that loads a Highchart.js area graph by passing some variables to it. Here's how I am using the directive: <andamento-fondo-area-chart color="#3FAE2A" url="../data.json"></andamento-fondo-a ...

Managing HTTP requests with errors within a forEach loop in Angular 9

I am currently coding a script that iterates through an array to make HTTP requests. Most of these requests are directed towards non-existent resources, but I do not have information on which ones specifically. Here is the code snippet I am using: ...

Employing setTimeout within a repetitive sequence

function displayColors() { $.each(colors, function(index) { setTimeout(function(){ revealColor(colors[index]); }, 1000); }); } I'm attempting to create a loop where the revealColor function is executed every second until all colors ...

Node modules are incapable of being installed within node packages

Whenever I use the ng serve command in my terminal, an error pops up: 10% building 3/3 modules 0 activei 「wds」: Project is running at http://localhost:4200/webpack-dev-server/ i 「wds」: webpack output is served from / i 「wds」: 404s will fall ...

Issue with Material UI Textfield functionality on mobile Safari browser

UPDATE: Resolved the problem by including this code in index.css input { -webkit-user-select:text;} In my application, I am using a Material UI box that contains text fields with an onChange handler. While the TextFields function correctly on most bro ...

Error: The Mui Material Breakpoints Theme Cannot Be Located

Hello there! I'm having some trouble placing my code breakpoints, resulting in an error in the output. Can you help me? import { makeStyles } from "@material-ui/styles"; const useStyle = makeStyles((theme)=>({ LogoLg:{ display:&ap ...

Deciphering JSON data in an Express.js application

In a Node.js/Express.js application, an API call is made to another server which responds with JSON data. However, the received JSON response is not being properly parsed into new variables. What specific modifications should be applied to the code below i ...

Locate an object for editing or adding changes

My scenario involves the existence of an object named productCounts [{provisioned=2.0, product=str1, totalID=1.0}, {product=str2, provisioned=4.0, totalID=3.0}, {provisioned=6.0, product=str3, totalID=5.0}] In addition, there is an array labeled uniqu ...

Incorporating an HTML/Javascript game into a reactJS website: A step-by-step

After developing a game using plain javascript and HTML along with a few JS libraries, I find myself inquiring about the process of integrating this game into my ReactJS website. Typically, the game is initiated by opening the index.html file located with ...

Trouble arises when adding a .js script to the webpage

I'm feeling quite puzzled by this small piece of code, as it appears to be the simplest thing you'll come across today. Despite that, I can't help but seek guidance because I've been staring at it for what feels like an eternity and can ...

Is there a way to send an array of objects to my Express / SQL Server in react?

I am currently facing a challenge with passing an array of objects to my back end (SQL Server). Below is the specific array of objects: console.info(results) Here is the array of objects named results: [0] [ [0] { [0] answer: 'bmbm,nn', [ ...

Update the Angular material table with the set filtered results

Currently, I have a functioning Angular Material table with search capabilities. However, I am encountering an issue. The problem lies in the fact that when I navigate from 'route A' to 'route B' and pass a value to the search box in t ...

When initiating a new browser window with JQuery, some data is not being transmitted

Encountering an issue with the windows.open(); method. Tech Stack: Asp.netMVC, C#, Razor Problem: jQuery When the function is triggered, it should send parameters to the Actioid and taskid controllers. However, I am facing an issue where only Actioid and ...

Avoiding infinite loops in JavaScript events

This particular issue involves functions specific to D3, but is not limited to D3. I have developed two D3 charts and implemented zoom functionality on both with the intention of synchronizing the zoom scale and position - so that when one chart is zoomed, ...

Javascript - Error encountered when utilizing a for loop to insert a new column into an array

I have been utilizing an API to fetch data on various stocks, and I am attempting to include a column named "symbol" with the query values using the function insertColumn. However, I am encountering an error message that says (node:15732) UnhandledPromiseR ...

What is the process of organizing information with http in Angular 2?

Currently, I am working through a heroes tutorial and have made progress with the code so far. You can view the code <a href="https://plnkr.co/edit/YHzyzm6ZXt4ESr76mNuB?preview" rel="nofollow noreferrer">here</a>. My next goal is to implement ...

The announcement will not be made as a result of the utilization of a private name

I've been working on transitioning a project to TypeScript, and while most of the setup is done, I'm struggling with the final steps. My goal is to use this TypeScript project in a regular JavaScript project, so I understand that I need to genera ...