Soru Typescript'te jenerik sınıftaki type parametresinden yeni bir nesne nasıl oluşturulur?


Genel sınıfımda yeni bir tür parametresi oluşturmaya çalışıyorum. Benim sınıfımda "Görünüm" tür parametreleri olarak geçirilen genel türden nesnelerin 2 listesi var, ancak yapmaya çalıştığımda new TGridView() yazı tipi diyor Could not find symbol 'TGridView'...

Bu kod:

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;
        }
    }
}

Genel bir türden nesne oluşturabilir miyim?


76
2018-06-29 16:10


Menşei




Cevaplar:


Derlenmiş JavaScript'in tüm tip bilgileri sildiğinden, kullanamazsınız T bir nesneyi yenilemek.

Bunu, türünü yapıcıya geçirerek jenerik olmayan bir şekilde yapabilirsiniz.

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();

Bu örneği, türleri sıkıştırmak için jeneriklerle genişletebilirsiniz:

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();

51
2018-06-29 19:16



Bu süper temiz ve harika çalışıyor! - Jaume Mussons Abad


Genel kod içinde yeni bir nesne oluşturmak için, yapıcı işlevine göre türe başvurmanız gerekir. Yani bunu yazmak yerine:

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

Bunu yazman gerek:

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

var classA: ClassA = activator(ClassA);

Bu soruya bakın: Sınıf Bağımsız Değişkeni ile Genel Tür Çıkarımı


87
2017-11-02 05:52



Biraz geç (ama kullanışlı) yorum - yapıcınız args alırsa new() aynı zamanda - veya daha genel bir ihtiyacı: type: {new(...args : any[]): T ;} - Rycochet
Nedir IActivatable? Herhangi bir dokümanda bulamıyorum. - Yoda
@Yoda IActivatable kendi oluşturduğunuz bir arayüzdür, diğer soruya bakınız: stackoverflow.com/questions/24677592/... - Jamie


Tüm tip bilgileri JavaScript tarafında silinir ve bu nedenle de @Sohnee durumları gibi T'yi yenemezsiniz, ancak yapıcıya iletilen parametreyi yazmayı tercih ederim:

class A {
}

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

var test = new B<A>(A);

15
2018-01-18 13:39





export abstract class formBase<T> extends baseClass {

  protected item = {} as T;
}

Nesnesi herhangi bir parametre alabilecektir, ancak T tipi sadece bir yazı referansıdır ve bir kurucu tarafından oluşturulamaz. Yani, herhangi bir alt sınıf nesnesi oluşturmaz.


7
2018-01-16 11:53



Lütfen oku Nasıl cevap ve bu kodun ne yaptığını açıklar. - CodeCaster
DikkatBu işe yarayabilir, ancak sonuçta ortaya çıkan nesne Type olamaz TYani, herhangi bir alıcı / belirteç T çalışmayabilir. - Daniel Ormeño
@ DanielOrmeño açıklamak ister misiniz? Bununla ne demek istiyorsun? Kodum bu snippet'i kullanarak çalışıyor gibi görünüyor. Teşekkürler. - eestein
Javascript yorumlanmış bir dildir ve el yazması henüz türlere veya sınıflara referans vermez. Bu yüzden T sadece yazı tipi için bir referanstır. - jalescardoso


Bunu kullanıyorum: let instance = <T>{}; genellikle çalışır DÜZEN 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]);
  }
}

0
2017-10-03 15:07



Bu aslında yeni bir örneği başlatmayacak Tsadece TypeScript'in boş bir nesneyi oluşturacaktır. düşünüyor tipi T. Cevabınızı biraz daha ayrıntılı açıklamak isteyebilirsiniz. - Sandy Gifford
Genelde çalıştığını söyledim. Aynen söylediğin gibi. Derleyici sızlanmak değil ve genel kodunuz var. Açık bir yapıcıya ihtiyaç duymadan istediğiniz özellikleri manuel olarak ayarlamak için bu örneği kullanabilirsiniz. - Bojo


Jenerik bir temel sınıfın içinden başlatmaya çalışıyordum. Yukarıdaki örneklerden hiçbiri, fabrika yöntemini çağırmak için somut bir tip gerektirdiğinden benim için çalışmadı.

Bir süredir bunun için araştırdıktan ve çevrimiçi bir çözüm bulamadıktan sonra, bunun işe yarayacağını keşfettim.

 protected activeRow: T = {} as T;

Parçalar:

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

...

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

Hep birlikte

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

0
2017-10-09 22:54