Определение типа, которое экспортирует определение как типа, так и класса в пространство имен

Я работаю над определением типа для сторонней библиотеки 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'.

Попробуйте это в игровая площадка.

Мой текущий обходной путь - дать

Попробуйте это в игровая площадка.

Как правильно это сделать, чтобы в первом примере использования (все после export default Car) вели себя так, как ожидалось?


person Aaron Beall    schedule 05.02.2019    source источник


Ответы (1)


Трудность, с которой вы сталкиваетесь, вызвана попыткой решить две проблемы одновременно: объявление типа и публикация типа (отсутствие лучшего термина).

Решение состоит в том, чтобы сначала объявить типы, а затем связать их, чтобы они соответствовали форме, представленной (опубликованной) библиотекой 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 { }

Вот ссылка на игровую площадку

person unional    schedule 05.02.2019