मैं पर्यवेक्षक पैटर्न जैसी संरचना के लिए टाइपस्क्रिप्ट लिखने की कोशिश कर रहा हूं और मैं इसे हासिल करने में असफल रहा हूं। मुझे लगता है कि मैं लगभग पूरा कर चुका हूं लेकिन किसी कारण से मुझे समझ में नहीं आता कि टीएस शिकायत क्यों कर रहा है।

type OnChangeListener = (object: object, from: string, to: string) => void
type OnCreateListener = (object: object) => void

type ListenerTypes = {
    onChange: OnChangeListener,
    onCreate: OnCreateListener
}

type Listener<T extends keyof ListenerTypes> = ListenerTypes[T]

type Listeners = {
    onChange: OnChangeListener[],
    onCreate: OnCreateListener[]
}

class SomeClass {
    private listeners: Listeners = {
        onChange: [],
        onCreate: []
    }

    public create(object: object) {
        this.listeners.onCreate.forEach(listener => listener(object))
    }

    public change(object: object, from: string, to: string) {
        this.listeners.onChange.forEach(listener => listener(object, from, to))
    }

    public registerListener<T extends keyof ListenerTypes>(name: T, listener: Listener<T>): void
    {
        this.listeners[name].push(listener) // <-- here is a problem
        /*
Argument of type 'Listener<T>' is not assignable to parameter of type 'OnCreateListener'.
  Type 'OnChangeListener | OnCreateListener' is not assignable to type 'OnCreateListener'.
    Type 'OnChangeListener' is not assignable to type 'OnCreateListener'
        */
    }
}

const someObject = new SomeClass()

someObject.registerListener("onChange", (o, from, to) => {}) // <-- this is ok
someObject.registerListener("onCreate", (o) => {}) // <-- this is ok
someObject.registerListener("onCreate",  (o, from, to) => {}) // <-- this error is ok, as the callback should be different

जब मैं श्रोताओं के प्रकार को में बदलता हूं

type Listeners = {
    onChange: any[],
    onCreate: any[]
}

फिर रजिस्टर फ़ंक्शन ठीक काम करता है, लेकिन ट्रिगर श्रोता ऑब्जेक्ट पर किसी भी प्रकार को स्पष्ट रूप से प्रदर्शित नहीं करता है। तो वहाँ विकल्प है कि मुझे क्या पसंद नहीं है। मैं यहाँ क्या गलत कर रहा हूँ?

1
Greg 23 नवम्बर 2020, 17:37

1 उत्तर

सबसे बढ़िया उत्तर

यदि आप अनुक्रमणिका प्रकार पर एक नज़र डालें तो उदाहरण दस्तावेज़ों में, ऐसा लगता है कि सामान्य रूप से अनुक्रमण केवल तभी काम करता है जब वस्तु का प्रकार अनुक्रमित किया जा रहा है, इसके बाहर किसी विशिष्ट वस्तु के विपरीत, फ़ंक्शन के सामान्य संदर्भ का हिस्सा है।

registerListener फ़ंक्शन के अंदर, this.listeners[name].push(listener) में listener का प्रकार OnChangeListener और OnCreateListener का प्रतिच्छेदन होने की उम्मीद है क्योंकि यह नहीं जानता कि क्या name "onChange" या "onCreate" होगा और इस प्रकार केवल फ़ंक्शन हस्ताक्षर स्वीकार करेगा जो दोनों पर लागू होते हैं। टाइपस्क्रिप्ट जेनेरिक इंडेक्स मैजिक नहीं करता है जब तक कि ऑब्जेक्ट प्रकार भी सामान्य न हो।

चूँकि registerListener करता है श्रोता के हस्ताक्षर में ठीक से भेदभाव करता है जिसे दी गई कुंजी के लिए पारित किया जाना चाहिए, मुझे लगता है कि सबसे अच्छा समाधान सिर्फ टाइपस्क्रिप्ट को यह बताना है कि जिस श्रोता सरणी तक आप पहुंच रहे हैं वह श्रोता से मेल खाता है .


public registerListener<T extends keyof ListenerTypes>(name: T, listener: Listener<T>): void {
    (this.listeners[name] as Listener<T>[]).push(listener);  
}
1
ABabin 23 नवम्बर 2020, 16:46