Создать новый объект из параметра типа в универсальном классе


Я пытаюсь создать новый объект параметр тип в моем классе. В моем классе View, У меня есть 2 списка объектов универсального типа, переданных в качестве параметров типа, но когда я пытаюсь сделать new TGridView(), машинопись говорит:

не удалось найти символ ' TGridView

этот код:

module AppFW {
    // Represents a view
    export class View<TFormView extends FormView, TGridView extends GridView> {
        // The list of forms 
        public Forms: { [idForm: string]: TFormView; } = {};

        // The list of grids
        public Grids: { [idForm: string]: TGridView; } = {};

        public AddForm(formElement: HTMLFormElement, dataModel: any, submitFunction?: (e: SubmitFormViewEvent) => boolean): FormView {
            var newForm: TFormView = new TFormView(formElement, dataModel, submitFunction);
            this.Forms[formElement.id] = newForm;
            return newForm;
        }

        public AddGrid(element: HTMLDivElement, gridOptions: any): GridView {
            var newGrid: TGridView = new TGridView(element, gridOptions);
            this.Grids[element.id] = newGrid;
            return newGrid;
        }
    }
}

можно ли создавать объекты из универсального типа?

6 84

6 ответов:

поскольку в скомпилированном JavaScript вся информация о типе стерта, вы не можете использовать T новый объект.

вы можете сделать это в общем виде, передав в конструктор.

class TestOne {
    hi() {
        alert('Hi');
    }
}

class TestTwo {
    constructor(private testType) {

    }
    getNew() {
        return new this.testType();
    }
}

var test = new TestTwo(TestOne);

var example = test.getNew();
example.hi();

вы можете расширить этот пример, используя дженерики подкрутить типа:

class TestBase {
    hi() {
        alert('Hi from base');
    }
}

class TestSub extends TestBase {
    hi() {
        alert('Hi from sub');
    }
}

class TestTwo<T extends TestBase> {
    constructor(private testType: new () => T) {
    }

    getNew() : T {
        return new this.testType();
    }
}

//var test = new TestTwo<TestBase>(TestBase);
var test = new TestTwo<TestSub>(TestSub);

var example = test.getNew();
example.hi();

чтобы создать новый объект в универсальном коде, необходимо обратиться к типу с помощью функции конструктора. Поэтому вместо того, чтобы писать это:

function activatorNotWorking<T extends IActivatable>(type: T): T {
    return new T(); // compile error could not find symbol T
}

вам нужно написать следующее:

function activator<T extends IActivatable>(type: { new(): T ;} ): T {
    return new type();
}

var classA: ClassA = activator(ClassA);

посмотреть этот вопрос: вывод универсального типа с аргументом класса

вся информация о типе стирается на стороне JavaScript, и поэтому вы не можете создать T так же, как состояния @Sohnee, но я бы предпочел, чтобы типизированный параметр передавался в конструктор:

class A {
}

class B<T> {
    Prop: T;
    constructor(TCreator: { new (): T; }) {
        this.Prop = new TCreator();
    }
}

var test = new B<A>(A);
export abstract class formBase<T> extends baseClass {

  protected item = {} as T;
}

его объект сможет получить любой параметр, однако тип T является только ссылкой на typescript и не может быть создан с помощью конструктора. То есть он не будет создавать никаких объектов подкласса.

Я использую этот: let instance = <T>{}; это вообще работает Редактировать 1:

export class EntityCollection<T extends { id: number }>{
  mutable: EditableEntity<T>[] = [];
  immutable: T[] = [];
  edit(index: number) {
    this.mutable[index].entity = Object.assign(<T>{}, this.immutable[index]);
  }
}

Я пытался создать экземпляр generic из базового класса. Ни один из приведенных выше примеров не работал для меня, поскольку они требовали конкретного типа для вызова метода фабрики.

после исследования на некоторое время на этом и не в состоянии найти решение в Интернете, я обнаружил, что это, кажется, работает.

 protected activeRow: T = {} as T;

штук:

 activeRow: T = {} <-- activeRow now equals a new object...

...

 as T; <-- As the type I specified. 

все вместе

 export abstract class GridRowEditDialogBase<T extends DataRow> extends DialogBase{ 
      protected activeRow: T = {} as T;
 }