Определение типа, которое экспортирует определение типа и класса в пространство имен - PullRequest
0 голосов
/ 05 февраля 2019

Я работаю над определением типа для сторонней библиотеки 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) ведет себя как ожидалось?

1 Ответ

0 голосов
/ 05 февраля 2019

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

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

Вот ссылка детская площадка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...