属性 在带有 TypeScript 的 Phaser 上的联合类型上不存在
Property does not exist on union type on Phaser with TypeScript
我一直在按照本教程 https://learn.yorkcs.com/2019/02/07/build-a-space-shooter-with-phaser-3-3/ 来使用 Phaser 3 制作游戏,但是因为我想在线部署它们,所以我将代码转换为与 TypeScript 一起使用,因为我正在通过 Ionic 准备它5 应用程序。在教程中,我应该设置玩家精灵的速度。为清楚起见,我必须创建两个 classes,Entities.js
(我创建为 entities.ts
)和 Player.js
(我创建为 player.ts
)。实体应该是 Phaser.GameObjects.Sprite
的扩展,玩家应该是实体,扩展实体 class。到目前为止,除了达到设置玩家速度的部分外,我的一切都正常工作。
这是我的 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);
}
}
这是我的 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);
}
}
一旦我写了行,this.body.setVelocity(0, 0)
,我得到一个错误:Property 'setVelocity' does not exist on type 'Body | StaticBody | BodyType'. Property 'setVelocity' does not exist on type 'StaticBody'
。显然,精灵的主体可以用于 Body
、StaticBody
或 BodyType
对象。检查文档,Body
class https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.Body.html allows for the setVelocity
function to happen, whereas the StaticBody
one https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.StaticBody.html 没有。
TypeScript 是否期望每种可能的类型都支持要使用的函数?如果是这样,我有没有办法指定我使用的 body
类型?我尝试解析无济于事。
现在,我认为可能有一种方法可以指定我希望在普通 JavaScript https://uptoskill.com/ionic-react-javascript/ 中开发的 Ionic,但如果不求助于此,是否有一种方法可以指定我希望在我的函数调用中使用 union?请告诉我,感谢您的帮助。
错误消息表明您的播放器主体是这些类型之一'Body | StaticBody | BodyType'
,但 StaticBody 没有 setVelocity
方法。 Typescript 有 typeguards 的概念来处理这种情况,您可以在其中使用具有不同成员的联合类型。
此处的解决方案是检查 this.body 是否具有 setVolicity 函数。
update() {
// when true typescript know it is not a StaticBody
if ("setVelocity" in this.body)
this.body.setVelocity(0, 0);
}
您还可以定义自定义类型保护函数并在 if 语句中使用它,如下所示:
//custom typeguard function with the return type '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);
}
正如 jcalz 所解释的那样,答案是测试所讨论的对象是否是包含要调用的函数的 class 的实例。换句话说,要确保我们希望使用 Body
而不是 StaticBody
。这可以通过简单地检查对象中是否存在该函数来完成:
if('setVelocity' in this.body) {
this.body.setVelocity(0, 0);
}
更具体地说,我们可以通过以下方式检查对象是否是预期对象的实例:
if(this.body instanceof Phaser.Physics.Arcade.Body) {
this.body.setVelocity(0, 0);
}
我一直在按照本教程 https://learn.yorkcs.com/2019/02/07/build-a-space-shooter-with-phaser-3-3/ 来使用 Phaser 3 制作游戏,但是因为我想在线部署它们,所以我将代码转换为与 TypeScript 一起使用,因为我正在通过 Ionic 准备它5 应用程序。在教程中,我应该设置玩家精灵的速度。为清楚起见,我必须创建两个 classes,Entities.js
(我创建为 entities.ts
)和 Player.js
(我创建为 player.ts
)。实体应该是 Phaser.GameObjects.Sprite
的扩展,玩家应该是实体,扩展实体 class。到目前为止,除了达到设置玩家速度的部分外,我的一切都正常工作。
这是我的 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);
}
}
这是我的 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);
}
}
一旦我写了行,this.body.setVelocity(0, 0)
,我得到一个错误:Property 'setVelocity' does not exist on type 'Body | StaticBody | BodyType'. Property 'setVelocity' does not exist on type 'StaticBody'
。显然,精灵的主体可以用于 Body
、StaticBody
或 BodyType
对象。检查文档,Body
class https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.Body.html allows for the setVelocity
function to happen, whereas the StaticBody
one https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.StaticBody.html 没有。
TypeScript 是否期望每种可能的类型都支持要使用的函数?如果是这样,我有没有办法指定我使用的 body
类型?我尝试解析无济于事。
现在,我认为可能有一种方法可以指定我希望在普通 JavaScript https://uptoskill.com/ionic-react-javascript/ 中开发的 Ionic,但如果不求助于此,是否有一种方法可以指定我希望在我的函数调用中使用 union?请告诉我,感谢您的帮助。
错误消息表明您的播放器主体是这些类型之一'Body | StaticBody | BodyType'
,但 StaticBody 没有 setVelocity
方法。 Typescript 有 typeguards 的概念来处理这种情况,您可以在其中使用具有不同成员的联合类型。
此处的解决方案是检查 this.body 是否具有 setVolicity 函数。
update() {
// when true typescript know it is not a StaticBody
if ("setVelocity" in this.body)
this.body.setVelocity(0, 0);
}
您还可以定义自定义类型保护函数并在 if 语句中使用它,如下所示:
//custom typeguard function with the return type '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);
}
正如 jcalz 所解释的那样,答案是测试所讨论的对象是否是包含要调用的函数的 class 的实例。换句话说,要确保我们希望使用 Body
而不是 StaticBody
。这可以通过简单地检查对象中是否存在该函数来完成:
if('setVelocity' in this.body) {
this.body.setVelocity(0, 0);
}
更具体地说,我们可以通过以下方式检查对象是否是预期对象的实例:
if(this.body instanceof Phaser.Physics.Arcade.Body) {
this.body.setVelocity(0, 0);
}