Класс машинописи Typeof не присваивается классу, который его расширяет. - PullRequest
0 голосов
/ 08 июля 2019

У нас есть базовый класс StoreObject, который предоставляет общие методы преобразования / очистки и т. Д. Для объектов, сохраняемых в БД. Я хотел бы иметь возможность указывать более строгие типы возврата из этих методов с использованием обобщений. Тем не менее, мои попытки приводят к ошибкам при сравнении typeof StoreObject с typeof AClassThatExtendsStoreObject, что мы делаем в различных служебных функциях. Можете ли вы указать мне в направлении того, что я делаю неправильно в приведенном ниже?


class StoreObject<S> {
  toStoreObject(s: S): S {
    // Perform some sanitisation etc.
    return s;
  }
}

interface Fact {
  id: string;
  fact: string;
}

// A concrete implementation of StoreUnit where we attempt to define the actual model of the object being stored
class FactStoreObject extends StoreObject<Fact> {}

// We've got some general utils that interact objects using these classes 
// These typicallay take a concrete implementation of StoreUnit to be used as a parser/processer
function doSomething(StoreObjectClass: typeof StoreObject) {
  // Typically:
  // const parsedObject = new StoreObjectClass(someObject).toStoreObject()
  // persistToDb(parsedObject)
}

// This errors with "Type 'S' is not assignable to type 'Fact'"
doSomething(FactStoreObject);

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

Ответы [ 2 ]

1 голос
/ 08 июля 2019

Ошибка из-за этой строки:

const parsedObject = new StoreObjectClass(someObject)

Во-первых, вам нужен конструируемый интерфейс:

export interface IConstructable<T> {
    new (): T;
}

Во-вторых, вам нужно включить параметр типа в метод фабрики:

function doSomething<T>( t: IConstructable<T> ) {
  const parsedObject = ( new t() ).toStoreObject();
  // persistToDb(parsedObject);
}
0 голосов
/ 08 июля 2019

В предоставленном коде в функции «doSomething» тип параметра указывается как «StoreObject» без универсального типа, который он просматривает. Чтобы исправить ошибку, вам нужно сделать что-то вроде:

  1. Передать универсальный параметр для "StoreObject" ( Факт в данном случае) в doSomthing .
  2. Параметр функции doSomething должен указывать тип с сигнатурой конструктора, который позволяет создавать новый экземпляр.

    Вот пример:

function doSomething<T>(StoreObjectClass: { new(): StoreObject<T> }) {
  // typically
  const someObject = <any>{id: "001", fact: "A real fact"};
  const parsedObject = new StoreObjectClass().toStoreObject(someObject);
  // persistToDb(parsedObject)
}

doSomething<Fact>(FactStoreObject);
...