Я работаю над определением типа для сторонней библиотеки 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'.
Попробуйте в детская площадка .
Мой текущий способ - дать внутреннему пространству имен другое имя, как _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 { }
Попробуйте на игровой площадке .
Какой правильный способ сделать это, так что использование первого примера (все после export default Car
) ведет себя как ожидалось?