【问题标题】:Why is my parameter assumed to be of one type when it is actually another?为什么我的参数实际上是另一种类型时被假定为一种类型?
【发布时间】:2018-02-24 11:58:46
【问题描述】:

为什么我必须将类型定义从material: Material | Material[]; 修改为material: Material; 才能修复下面详述的错误? TypeScript 似乎假设 material 参数的类型为 Material[],即使我明确将其设置为 Material。我错过了什么吗?

Typescript/ThreeJS 错误:

this.obj3D.traverse((child) => {
    if (child instanceof THREE.Mesh) {
        // Error in line below:
        // Property 'shading' does not exist on type 'Material | Material
        child.material.shading = THREE.SmoothShading;
        child.material.side = THREE.DoubleSide;
        child.scale.set(this.scale, this.scale, this.scale);
        child.castShadow = this.castShadow;
        child.receiveShadow = true;
        child.material.needsUpdate = true;
    }
});

三JS类型定义:

export class Mesh extends Object3D {
    constructor(geometry?: Geometry, material?: Material | Material[]);
    constructor(geometry?: BufferGeometry, material?: Material | Material[]);

    geometry: Geometry | BufferGeometry;
    material: Material | Material[]; // Had to delete *| Material[]* to fix
    drawMode: TrianglesDrawModes;

    setDrawMode(drawMode: TrianglesDrawModes): void;
    updateMorphTargets(): void;
    getMorphTargetIndexByName(name: string): number;
    raycast(raycaster: Raycaster, intersects: any): void;
}

【问题讨论】:

标签: typescript three.js


【解决方案1】:

据我从您的屏幕截图中可以看出,Mesh 对象的material 属性可以是Material 对象Material 对象的数组。 TypeScript 有用地警告您,您将 child.material 视为单个 Material 对象,而不检查它是否真的是一个对象。

除非您绝对确定您的代码将接触到的每个Mesh 实例都有一个Material 对象而不是数组作为其material 属性,否则您最好不要更改其中的类型定义图书馆。如果库声明文件是正确的并且某些Mesh 对象具有Material 对象的数组,那么一旦您尝试设置数组的shading 属性,您的代码就会在运行时出现错误行为。

相反,正确的做法是检查child.material 是否是一个数组,例如:

  const doStuffToMaterial = function(m: Material):void {
     m.shading = THREE.SmoothShading; 
     m.side = THREE.DoubleSide;
  }
  // check for an array
  if (Array.isArray(child.material)) {
    child.material.forEach(doStuffToMaterial);
  } else {
    doStuffToMaterial(child.material);
  }

它通过对每个元素执行相同的操作来处理数组情况。

或者,如果您确定 child.material 不是 数组,您可以执行以下操作:

  // Assert that it's not an array
  const m = child.material as Material; 
  m.shading = THREE.SmoothShading; 
  m.side = THREE.DoubleSide;

你告诉 TypeScript 你知道child.material 不是一个数组,通过使用类型断言。如果你的断言被证明是错误的,这仍然可能在运行时做坏事,但大概你知道得更好。

我希望其中一种解决方案对您有用。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多