学习BabylonJS,编写开关运行,报以下错误
import { Engine, Scene, ArcRotateCamera, Vector3, HemisphericLight, SpriteManager, Sprite, MeshBuilder, StandardMaterial, Texture, Color3, SceneLoader, CubeTexture, Mesh, ParticleSystem, Color4, PointerInfo, PointerEventTypes } from "@babylonjs/core";
import "@babylonjs/loaders";
import { CreateSceneClass } from "../createScene";
export class SpriteTrees implements CreateSceneClass {
createScene = async (
engine: Engine,
canvas: HTMLCanvasElement
) : Promise<Scene> => {
const scene = new Scene(engine);
this.showDebug(scene);
const arcRotateCamera = new ArcRotateCamera("arcRotateCamera", -Math.PI / 2, Math.PI / 2.5, 15, new Vector3(0, 0, 0), scene);
arcRotateCamera.upperBetaLimit = Math.PI / 2.2;
arcRotateCamera.attachControl(canvas, true);
const hemisphericLight = new HemisphericLight("hemisphericLight", new Vector3(1, 1, 0), scene);
//Swith fountain on and off
let switched = false;
const pointerDown = (mesh : Mesh) => {
if (mesh === fountain) {
switched = ! switched;
if(switched) {
// Start the particle system
particleSystem.start();
} else {
// Stop the particle system
particleSystem.stop();
}
}
}
scene.onPointerObservable.add((pointerInfo : PointerInfo) => {
switch (pointerInfo.type) {
case PointerEventTypes.POINTERDOWN:
if (pointerInfo.pickInfo?.hit) {
pointerDown(pointerInfo.pickInfo.pickedMesh);
}
break;
}
});
SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "valleyvillage.glb");
return scene;
};
export default new SpriteTrees();
运行显示如下:
ERROR in /***/***/***.ts(35,41)
TS2345: Argument of type 'Nullable<AbstractMesh>' is not assignable to parameter of type 'Mesh'.
Type 'null' is not assignable to type 'Mesh'.
该错误提示的意思是正在尝试将 pointerInfo.pickInfo.pickedMesh 作为参数传递给 pointerDown 函数,但是该函数期望接收的参数类型是 Mesh,而 pointerInfo.pickInfo.pickedMesh 的类型是 Nullable<AbstractMesh>,即可为空的抽象网格类型,这意味着可能存在传递 null 的情况,而 null 无法分配给 Mesh 类型。
为了解决这个问题,可以使用类型断言来确保传递的参数是 Mesh 类型而不是可为空的抽象网格类型。具体来说,您可以这样写:
pointerDown(pointerInfo.pickInfo.pickedMesh as Mesh);
使用 as 关键字将 pointerInfo.pickInfo.pickedMesh 显式地强制转换为 Mesh 类型,这样即使其为空,也不会引起类型错误。
总结
TypeScript基础掌握不足,对as 关键字不熟悉,下面让我们看下as关键字相关知识:
在 TypeScript 中,使用 as 关键字可以进行类型断言,即将某个值强制转换成特定的类型。类型断言有两种形式,一种是尖括号语法,一种是 as 语法。
尖括号语法的形式如下:
let str: any = '123';
let num: number = (<string>str).length;
as 语法的形式如下:
let str: any = '123';
let num: number = (str as string).length;
as 语法与尖括号语法相比,更加易读和不容易出错。但是需要注意的是,as 语法只能用于将某个值转换成更具体的类型或者相互兼容的类型,否则会导致编译错误。
下面是一个实例,假设我们有一个对象数组,数组中的每个对象都有一个 name 属性,但是这个属性可能是字符串类型,也可能是 undefined。我们想要将这个属性全部转换成字符串类型,并且去掉空字符串。
interface User {
name?: string;
age: number;
}
const users: User[] = [
{ name: 'Alice', age: 18 },
{ name: undefined, age: 20 },
{ name: '', age: 22 },
];
const names: string[] = users.map((user) => user.name)
.filter((name) => name !== undefined && name !== '') // 过滤掉 undefined 和空字符串
.map((name) => name as string); // 将 name 强制转换成 string 类型
console.log(names); // ['Alice']
在上面的例子中,我们使用了 as 语法将 name 属性强制转换成了 string 类型,然后过滤掉了 undefined 和空字符串。