我正在为第三方JS库(Handsontable)的类型定义进行工作,该类库导出顶级API的类和名称空间,概念上是这样的:
import Car from "car-lib";
new Car(); // Create instances
Car.garage.get("mustang"); // Static top-level APIs.
这可以通过导出具有名称空间的class
成员的static
来建模。
但是,某些类静态名称空间会导出类定义,而我很难正确地暴露类型和类定义以供使用。
示例:
declare namespace Car {
namespace parts {
class Engine { vroom(); }
}
interface Parts {
EnginePart: typeof parts.Engine; // Error: Property 'Engine' does not exist on type 'Parts'.
}
}
declare class Car {
static parts: Car.Parts;
}
export default Car;
// This works as desired
let engine: Car.parts.Engine;
engine.vroom();
// This should work but I get:
// Error: Type 'Engine' is not a constructor function type.
class V8 extends Car.parts.EnginePart { }
// This does not work, as desired
class V6 extends Car.parts.Engine { } // Error: Property 'Engine' does not exist on type 'Parts'.
在the playground中尝试。
我当前的解决方法是给internal namespace a different name,就像_parts
一样,但这会导致一些问题:
declare namespace Car {
namespace _parts {
class Engine { vroom(); }
}
interface Parts {
EnginePart: typeof _parts.Engine;
}
}
declare class Car {
static parts: Car.Parts;
}
export default Car;
// This requires referencing the "_parts" for type annotation, yuck
let engine: Car._parts.Engine;
engine.vroom();
// This works as desired
class V8 extends Car.parts.EnginePart { }
// Problem: this should not be allowed (and will be a runtime error) but it is allowed
class V6 extends Car._parts.Engine { }
在the playground中尝试。
执行此操作的正确方法是什么,以使第一个示例的用法(export default Car
之后的所有内容)均符合预期?
答案 0 :(得分:0)
您遇到的困难是由于试图同时解决两个问题而引起的:类型声明和类型发布(缺少更好的术语)。
解决方案是先声明类型,然后将它们连接起来以匹配JavaScript库公开(公开)的形状。
declare namespace CarParts {
class CarEngine { vroom(); }
}
interface CarParts {
EnginePart: typeof CarParts.CarEngine;
}
declare namespace Car {
namespace parts {
type Engine = CarParts.CarEngine
}
}
declare class Car {
static parts: CarParts;
}
export default Car;
let engine: Car.parts.Engine;
engine.vroom();
// This works as desired
class V8 extends Car.parts.EnginePart { }
// This is shown as error as expected
class V6 extends Car.parts.Engine { }