सवाल टाइपस्क्रिप्ट में जेनेरिक क्लास में टाइप पैरामीटर से एक नई ऑब्जेक्ट कैसे बनाएं?


मैं अपनी जेनेरिक कक्षा में एक प्रकार पैरामीटर का एक नया ऑब्जेक्ट बनाने की कोशिश कर रहा हूं। मेरी कक्षा "व्यू" में मेरे पास जेनेरिक प्रकार की ऑब्जेक्ट्स की 2 सूची टाइप पैरामीटर के रूप में पास की गई है, लेकिन जब मैं बनाने की कोशिश करता हूं new TGridView() टाइपस्क्रिप्ट कहते हैं Could not find symbol '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;
        }
    }
}

क्या मैं सामान्य प्रकार से ऑब्जेक्ट्स बना सकता हूं?


76
2018-06-29 16:10


मूल




जवाब:


चूंकि संकलित जावास्क्रिप्ट में सभी प्रकार की जानकारी मिटा दी गई है, इसलिए आप इसका उपयोग नहीं कर सकते हैं 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();

51
2018-06-29 19:16



यह बहुत साफ है और शानदार काम करता है! - Jaume Mussons Abad


सामान्य कोड के भीतर एक नई वस्तु बनाने के लिए, आपको इसके कन्स्ट्रक्टर फ़ंक्शन द्वारा प्रकार को संदर्भित करने की आवश्यकता है। तो इसे लिखने के बजाय:

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

यह प्रश्न देखें: कक्षा तर्क के साथ सामान्य प्रकार अनुमान


87
2017-11-02 05:52



कुछ देर से (लेकिन उपयोगी) टिप्पणी - यदि आपका कन्स्ट्रक्टर तब तर्क देता है new() साथ ही साथ - या अधिक सामान्य: type: {new(...args : any[]): T ;} - Rycochet
क्या है IActivatable? मैं इसे किसी भी दस्तावेज़ में नहीं ढूंढ सकता। - Yoda
@Yoda IActivatable एक स्वयं निर्मित इंटरफ़ेस है, अन्य प्रश्न देखें: stackoverflow.com/questions/24677592/... - Jamie


सभी प्रकार की जानकारी जावास्क्रिप्ट पक्ष में मिटा दी जाती है और इसलिए आप @ सोहेनी राज्यों की तरह टी को नया नहीं कर सकते हैं, लेकिन मैं कन्स्ट्रक्टर में टाइप किए गए टाइप पैरामीटर को प्राथमिकता देना पसंद करूंगा:

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

इसकी ऑब्जेक्ट किसी भी पैरामीटर को प्राप्त करने में सक्षम होगी, हालांकि, टाइप टी केवल एक टाइपस्क्रिप्ट संदर्भ है और इसे कन्स्ट्रक्टर के माध्यम से नहीं बनाया जा सकता है। यही है, यह किसी उप-वर्ग वस्तुओं को नहीं बनाएगा।


7
2018-01-16 11:53



कृपया पढ़ें जवाब कैसे दें और समझाओ कि यह कोड क्या करता है। - CodeCaster
खबरदार, यह काम कर सकता है लेकिन परिणामी वस्तु प्रकार का नहीं होगा T, इसलिए किसी भी गेटर्स / सेटर्स में परिभाषित किया गया है T काम नहीं कर सकता - Daniel Ormeño
@ डैनियल ऑर्मेनो को समझाने की देखभाल? उससे तुम्हारा क्या मतलब है? मेरा कोड इस स्निपेट का उपयोग कर काम कर रहा प्रतीत होता है। धन्यवाद। - eestein
जावास्क्रिप्ट एक व्याख्या की गई भाषा है और ecmascript में अभी तक प्रकार या कक्षाओं के संदर्भ नहीं हैं। तो टी टाइपस्क्रिप्ट के लिए सिर्फ एक संदर्भ है। - jalescardoso


मैं इसका उपयोग करता हूं: 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]);
  }
}

0
2017-10-03 15:07



यह वास्तव में एक नए उदाहरण को तत्काल नहीं करेगा T, यह सिर्फ एक खाली वस्तु बना देगा जो टाइपस्क्रिप्ट सोचता प्रकार का है T। आप अपने उत्तर को थोड़ा और विस्तार से समझा सकते हैं। - Sandy Gifford
मैंने कहा कि यह आम तौर पर काम करता है। जैसा आप कहते हैं वैसा ही है। कंपाइलर चमक नहीं रहा है और आपके पास सामान्य कोड है। आप इस उदाहरण का उपयोग मैन्युअल रूप से उन गुणों को सेट करने के लिए कर सकते हैं जिन्हें आप स्पष्ट कन्स्ट्रक्टर की आवश्यकता के बिना चाहते हैं। - Bojo


मैं जेनेरिक को बेस क्लास के भीतर से तुरंत चालू करने की कोशिश कर रहा था। उपर्युक्त उदाहरणों में से कोई भी मेरे लिए काम नहीं करता क्योंकि उन्हें फैक्ट्री विधि को कॉल करने के लिए ठोस प्रकार की आवश्यकता होती है।

इस पर थोड़ी देर के लिए शोध करने के बाद और ऑनलाइन समाधान खोजने में असमर्थ होने के बाद, मुझे पता चला कि यह काम पर प्रतीत होता है।

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

0
2017-10-09 22:54