इस प्रश्न के बाद, अब मैं एक स्पष्ट यह पैरामीटर एक प्रकार का एक्सटेंडिंग इंटरफ़ेस IModel:

// interface for Model class

interface IModel {
    state: {}
}

// based on answer to this question https://stackoverflow.com/q/59895071/374328
// now functions will be bound to model instance, so need to specify 'this' parameter as Model

type SingleArgFunction<Model extends IModel, A> = (this: Model, x: A) => A;
type ArrayedReturnFunction<Model extends IModel, A> = (this: Model, x: A) => A[];

type SingleArgFunctionObject<Model extends IModel, AS extends object> = {
    [K in keyof AS]: SingleArgFunction<Model, AS[K]>
}

type ArrayedReturnFunctionObject<Model extends IModel, AS extends object> = {
    [K in keyof AS]: ArrayedReturnFunction<Model, AS[K]>
}

function makeArrayed<Model extends IModel, A>(f: SingleArgFunction<Model, A>): ArrayedReturnFunction<Model, A> {
    return function (x) {
        return [f.call(this, x)];
    }
}

function makeArrayedAll<Model extends IModel, AS extends object>(
    fs: SingleArgFunctionObject<Model, AS>
): ArrayedReturnFunctionObject<Model, AS> {
    const result = {} as ArrayedReturnFunctionObject<Model, AS>;

    (Object.keys(fs) as (keyof AS)[]).forEach(function<K extends keyof AS>(key: K) {
        result[key] = makeArrayed(fs[key]);
    })
    return result;
}

एक उदाहरण मॉडल और प्रकार परिभाषाएँ:

interface MyModel extends IModel {
    state: {
        x: number;
    }
}

interface SingleArgFunctions {
    foo: SingleArgFunction<MyModel, number>
}

interface ArrayedReturnFunctions {
    foo: ArrayedReturnFunction<MyModel, number>;
}

ArrayedReturnFunctions का ऑब्जेक्ट बनाना सीधे ठीक है, this को MyModel प्रकार के रूप में अनुमानित किया जा रहा है:

const arrayedReturnFunctions1: ArrayedReturnFunctions = {
    foo(x) {
        return [x + this.state.x]; // ok
    }
}

वैकल्पिक रूप से, किसी एकल फ़ंक्शन में makeArrayed लागू करके ऑब्जेक्ट बनाना भी ठीक है:

const arrayedReturnFunctions2: ArrayedReturnFunctions = {
    foo: makeArrayed(function (x) {
        return x + this.state.x; // ok
    })
}

हालांकि, makeArrayedAll का उपयोग करने से काम नहीं चलता - this का अनुमान IModel प्रकार के रूप में लगाया जाता है:

const arrayedReturnFunctions3: ArrayedReturnFunctions = makeArrayedAll({
    foo(x) {
        return x + this.state.x; // error - property x does not exist on type {}
    }
})

यहां तक ​​​​कि SingleArgFunctions प्रकार का ऑब्जेक्ट बनाना और फिर उसे makeArrayedAll में पास करना काम नहीं करता है:

const singleArgFunctions: SingleArgFunctions = {
    foo(x) {
        return this.state.x + x;
    }
}

const arrayedReturnFunctions4 = makeArrayedAll(singleArgFunctions); // error - IModel is not assignable to type MyModel 

makeArrayedAll का उपयोग करते समय Model प्रकार को MyModel के रूप में अनुमानित क्यों नहीं किया जाता है?

खेल का मैदान

0
stw 26 जिंदा 2020, 19:59

1 उत्तर

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

मेरे लिए ऐसा लगता है कि आप arrayedReturnFunctions वेरिएबल के प्रकार की उम्मीद कर रहे हैं जिसके लिए आप makeArrayedAll() का आउटपुट असाइन कर रहे हैं, makeArrayedAll() के इनपुट के लिए पर्याप्त प्रासंगिक टाइपिंग प्रदान करेगा ताकि इनपुट मेथड्स' this संदर्भ का अनुमान लगाया जाएगा... लेकिन ऐसा नहीं हो रहा है। मुझे बिल्कुल आश्चर्य नहीं है कि इस परिदृश्य में प्रासंगिक अनुमान विफल हो जाएगा, लेकिन मेरे पास इस बारे में कोई अच्छा जवाब नहीं है कि इसे क्यों या कैसे होने के लिए मजबूर किया जाए।

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

मॉडल प्रकार पैरामीटर को मैन्युअल रूप से निर्दिष्ट करने का एक तरीका यहां दिया गया है और कंपाइलर को curring का उपयोग करके बाकी का अनुमान लगाने दें। :

const makeArrayedAllFor = <M extends IModel>() => <AS extends object>(
  fs: SingleArgFunctionObject<M, AS>) => makeArrayedAll(fs);

const arrayedReturnFunctions3: ArrayedReturnFunctions = makeArrayedAllFor<MyModel>()({
    foo(x) {
        return x + this.state.x;
    }
})

const arrayedReturnFunctions4 = makeArrayedAllFor<MyModel>()(singleArgFunctions);

यह अब काम करता है, हालांकि यह बोझिल है। इस समय मैं जो सबसे अच्छा सोच सकता हूं वह यही है; शायद किसी के पास अन्य विचार हैं? ओह अच्छा, शुभकामनाएँ!

खेल का मैदान लिंक

1
jcalz 26 जिंदा 2020, 21:38