बिल्ड टाइपप्रति में गुणों के साथ एक समारोह वस्तु

वोट
46

मैं एक समारोह वस्तु है, जो भी इस पर आयोजित कुछ गुण है बनाना चाहते हैं। जावास्क्रिप्ट में उदाहरण के लिए मुझे क्या करना होगा:

var f = function() { }
f.someValue = 3;

अब टाइपप्रति में मैं इस के रूप में के प्रकार का वर्णन कर सकते हैं:

var f: { (): any; someValue: number; };

हालांकि मैं वास्तव में, यह निर्माण नहीं कर सकते एक डाली की आवश्यकता के बिना। जैसे कि:

var f: { (): any; someValue: number; } =
    <{ (): any; someValue: number; }>(
        function() { }
    );
f.someValue = 3;

आप कैसे एक डाली के बिना इस का निर्माण होगा?

07/10/2012 को 07:08
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


9 जवाब

वोट
73

अपडेट: यह जवाब टाइपप्रति के पुराने संस्करणों में सबसे अच्छा समाधान था, लेकिन वहाँ बेहतर विकल्प नए संस्करणों (अन्य उत्तर देखें) में उपलब्ध हैं।

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

interface F { (): any; someValue: number; }

var f = <F>function () { }
f.someValue = 3

// type error
f.notDeclard = 3
05/09/2013 को 16:12
का स्रोत उपयोगकर्ता

वोट
34

टाइपप्रति के माध्यम से इस मामले को संभालने के लिए बनाया गया है घोषणा विलय :

आप भी एक समारोह बनाने और फिर समारोह पर गुण जोड़कर आगे समारोह के विस्तार के लिए जावास्क्रिप्ट अभ्यास के साथ परिचित हो सकते हैं। टाइपप्रति एक प्रकार सुरक्षित तरीके से इस तरह परिभाषाओं का निर्माण करने के घोषणा विलय का उपयोग करता है।

घोषणा विलय हमें का कहना है कि कुछ दोनों एक समारोह और एक नाम स्थान (आंतरिक मॉड्यूल) है देता है:

function f() { }
namespace f {
    export var someValue = 3;
}

यह टाइपिंग को बरकरार रखता है और हम दोनों लिखने की सुविधा देता है f()और f.someValue। जब एक लेखन .d.tsमौजूदा जावा स्क्रिप्ट कोड के लिए फ़ाइल, का उपयोग declare:

declare function f(): void;
declare namespace f {
    export var someValue: number;
}

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

28/10/2015 को 13:47
का स्रोत उपयोगकर्ता

वोट
27

अब यह आसानी से प्राप्त है (टाइपप्रति 2.x) के साथ Object.assign(target, source)

उदाहरण:

यहाँ छवि विवरण दर्ज

जादू है कि यहाँ है Object.assign<T, U>(...)एक वापस करने के लिए लिखा गया चौराहे के प्रकार T & U

लागू है कि यह एक जाना जाता इंटरफेस पर ले कर भी सीधी-सपाट है:

interface Foo {
  (a: number, b: string): string[];
  foo: string;
}

let method: Foo = Object.assign(
  (a: number, b: string) => { return a * a; },
  { foo: 10 }
); 

त्रुटि: foo: संख्या foo को आबंटित नहीं: स्ट्रिंग
त्रुटि: संख्या स्ट्रिंग [] (वापसी प्रकार) के लिए आबंटित नहीं

चेतावनी: यदि आप की आवश्यकता हो सकती polyfill पुराने ब्राउज़र लक्ष्यीकरण अगर Object.assign।

25/01/2017 को 13:43
का स्रोत उपयोगकर्ता

वोट
17

तो अगर आवश्यकता बस का निर्माण और एक डाली बिना कि कार्य करने के लिए "f" आवंटित करने के लिए है, यहाँ एक संभव समाधान है:

var f: { (): any; someValue: number; };

f = (() => {
    var _f : any = function () { };
    _f.someValue = 3;
    return _f;
})();

मूलतः, यह एक आत्म क्रियान्वित समारोह एक वस्तु है कि कि हस्ताक्षर से मेल करने से पहले काम किया जाता है "का निर्माण करने के लिए" शाब्दिक उपयोग करता है। केवल weirdness अन्यथा संकलक रोता है कि आप एक संपत्ति जो वस्तु पर अभी तक अस्तित्व में नहीं है बताए रहे हैं, वह समारोह के भीतर घोषणा प्रकार 'कोई भी' के होने की जरूरत है।

संपादित करें: कोड थोड़ा सरल बनाया गया।

07/10/2012 को 17:33
का स्रोत उपयोगकर्ता

वोट
1

मैं नहीं कह सकता कि यह बहुत सीधा है लेकिन यह निश्चित रूप से संभव है:

interface Optional {
  <T>(value?: T): OptionalMonad<T>;
  empty(): OptionalMonad<any>;
}

const Optional = (<T>(value?: T) => OptionalCreator(value)) as Optional;
Optional.empty = () => OptionalCreator();

यदि आप उत्सुक हो गया इस बात का टाइपप्रति / जावास्क्रिप्ट संस्करण के साथ मेरा एक सार से हैOptional

07/02/2018 को 23:57
का स्रोत उपयोगकर्ता

वोट
1

एक अद्यतन जवाब: के माध्यम से चौराहे प्रकार के अलावा के बाद से &, यह मक्खी पर "मर्ज" करने के लिए दो अनुमानित प्रकार संभव है।

यहाँ एक सामान्य सहायक है कि कुछ ऑब्जेक्ट के गुणों को पढ़ता है fromऔर एक वस्तु से अधिक उन्हें प्रतियां onto। यह रिटर्न एक ही वस्तु ontoहै, लेकिन एक नए प्रकार है कि गुण के दोनों सेट शामिल हैं, इसलिए सही ढंग से क्रम व्यवहार का वर्णन के साथ:

function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
    Object.keys(from).forEach(key => onto[key] = from[key]);
    return onto as T1 & T2;
}

यह निम्न स्तर के सहायक अभी भी एक प्रकार-जोर प्रदर्शन करता है, लेकिन यह प्रकार सुरक्षित डिजाइन कर रहा है। जगह में इस सहायक के साथ, हम एक ऑपरेटर है कि हम पूर्ण प्रकार सुरक्षा के साथ ओपी के समस्या को हल करने का उपयोग कर सकते हैं:

interface Foo {
    (message: string): void;
    bar(count: number): void;
}

const foo: Foo = merge(
    (message: string) => console.log(`message is ${message}`), {
        bar(count: number) {
            console.log(`bar was passed ${count}`)
        }
    }
);

टाइपप्रति खेल का मैदान में इसे आज़माने के लिए यहां क्लिक करें । ध्यान दें कि हम विवश है fooप्रकार की होनी चाहिए Foo, इसलिए का परिणाम mergeएक पूरा हो गया है Foo। तो अगर आप का नाम बदलने यदि barकरने के लिए badतो आप एक प्रकार त्रुटि मिलती है।

नायब वहाँ अभी भी यहाँ एक प्रकार छेद, हालांकि है। टाइपप्रति एक प्रकार पैरामीटर विवश करने के लिए "एक समारोह नहीं" होने का एक तरीका प्रदान नहीं करता है। तो अगर आप भ्रमित हो सकता है और करने के लिए दूसरा तर्क के रूप में अपने कार्य से पारित mergeहै, और वह काम नहीं करेंगे। तो जब तक यह घोषित किया जा सकता है, हम रनटाइम पर उसे पकड़ने के लिए है:

function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
    if (typeof from !== "object" || from instanceof Array) {
        throw new Error("merge: 'from' must be an ordinary object");
    }
    Object.keys(from).forEach(key => onto[key] = from[key]);
    return onto as T1 & T2;
}
10/03/2016 को 19:14
का स्रोत उपयोगकर्ता

वोट
1

एक शॉर्टकट के रूप में, आप गतिशील रूप से [ 'संपत्ति'] एक्सेसर का उपयोग कर वस्तु मान असाइन कर सकते हैं:

var f = function() { }
f['someValue'] = 3;

इस प्रकार की जाँच नजरअंदाज। हालांकि, यह बहुत सुरक्षित है क्योंकि आप जानबूझकर संपत्ति उसी तरह का उपयोग करना है:

var val = f.someValue; // This won't work
var val = f['someValue']; // Yeah, I meant to do that

हालांकि, अगर आप वास्तव में टाइप संपत्ति मान को चेक चाहते हैं, यह काम नहीं करेगा।

11/10/2012 को 05:38
का स्रोत उपयोगकर्ता

वोट
0

पुराने सवाल है, लेकिन 3.1 के साथ शुरू टाइपप्रति के संस्करणों के लिए, तो आप बस संपत्ति काम के रूप में आप सादे जे एस में होगा, जब तक कि आप एक समारोह घोषणा या का उपयोग कर सकते हैं constअपने चर के लिए कीवर्ड:

function f () {}
f.someValue = 3; // fine
const g = function () {};
g.someValue = 3; // also fine
var h = function () {};
h.someValue = 3; // Error: "Property 'someValue' does not exist on type '() => void'"

संदर्भ और ऑनलाइन उदाहरण

26/11/2018 को 21:38
का स्रोत उपयोगकर्ता

वोट
0

इस मजबूत टाइपिंग से रवाना, लेकिन आप क्या कर सकते हैं

var f: any = function() { }
f.someValue = 3;

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

"आप जावास्क्रिप्ट पूरी तरह से वैध टाइपप्रति कि" गलत का आकलन। (नोट: 0.95 का प्रयोग करके)

21/02/2014 को 16:59
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more