टाइपस्क्रिप्ट स्थिर कक्षाएं


145

मैं पारंपरिक JS से टाइपस्क्रिप्ट में जाना चाहता था क्योंकि मुझे C # जैसा सिंटैक्स पसंद है। मेरी समस्या यह है कि मैं टाइपस्क्रिप्ट में स्थिर कक्षाओं की घोषणा कैसे कर सकता हूं।

C # में, मैं अक्सर स्थिर वर्गों का उपयोग चर और विधियों को व्यवस्थित करने के लिए करता हूं, उन्हें एक नामित वर्ग में एक साथ रखा जाता है, बिना किसी वस्तु को उकसाने के लिए। वेनिला JS में, मैं एक साधारण JS ऑब्जेक्ट के साथ ऐसा करता था:

var myStaticClass = {
    property: 10,
    method: function(){}
}

टाइपस्क्रिप्ट में, मैं अपने सी-शार्पी दृष्टिकोण के लिए जाना चाहूंगा, लेकिन ऐसा लगता है कि स्थिर कक्षाएं टीएस में मौजूद नहीं हैं। इस समस्या का उचित समाधान क्या है?

जवाबों:


166

टाइपस्क्रिप्ट C # नहीं है, इसलिए आपको टाइपस्क्रिप्ट में C # की समान अवधारणाओं की अपेक्षा नहीं करनी चाहिए। सवाल यह है कि आप स्टैटिक क्लास क्यों चाहते हैं?

C # में एक स्थिर वर्ग केवल एक ऐसा वर्ग है जिसे उप-वर्ग नहीं किया जा सकता है और इसमें केवल स्थैतिक विधियाँ होनी चाहिए। C # किसी को कक्षाओं के बाहर के कार्यों को परिभाषित करने की अनुमति नहीं देता है। हालाँकि टाइपस्क्रिप्ट में यह संभव है।

यदि आप अपने कार्यों / विधियों को नाम स्थान (यानी वैश्विक नहीं) में रखने का कोई रास्ता खोज रहे हैं, तो आप टाइपस्क्रिप्ट मोड्स का उपयोग करने पर विचार कर सकते हैं, जैसे।

module M {
    var s = "hello";
    export function f() {
        return s;
    }
}

ताकि आप Mf () को बाहरी रूप से एक्सेस कर सकें, लेकिन एस नहीं, और आप मॉड्यूल का विस्तार नहीं कर सकते।

अधिक विवरण के लिए टाइपस्क्रिप्ट विनिर्देश देखें।


इसलिए एक मॉड्यूल में एक स्थिर विधि हो सकती है, लेकिन एक वर्ग नहीं कर सकता है? लेकिन मॉड्यूल में स्थैतिक डेटा नहीं हो सकता है। यह कुछ भी पल के बिना डेटा और कोड लपेटने के लिए जेएस के रूप में सुविधाजनक नहीं है।
dcsan

यह शामिल करने के लिए उपयोगी हो सकता है कि आपको .jsअपने में शामिल करने की आवश्यकता होगी html। तो Angular 2शायद आप उपयोग कर रहे हैं System... तो इससे पहले System.import("Folder/M");(या संकलित .jsफ़ाइल के लिए जो भी रास्ता है ) करना होगाbootstrap import
Serj Sagan

11
यह पदावनत है। इसके अलावा tslint आपको ऐसा नहीं करने देगा मॉड्यूल और नामस्थान के लिए। यहाँ पढ़ें: palantir.github.io/tslint/rules/no-namespace
फ्लोरियन

मेरे पास स्टैटिक क्लासेस होने का उपयोग-मामला है। अभी, मेरे पास एक वर्ग है जिसमें केवल स्थिर विधियाँ हैं। परियोजना में हमें प्रत्येक वर्ग के लिए कुछ प्रकार के कॉन्फ़िगरेशन प्रदान करने की आवश्यकता होती है, जिसे तत्काल किया जा सकता है। इस तरह के वर्ग को स्थिर घोषित करने से न केवल मुझे यह नोटिस करने में मदद मिलेगी कि यह त्वरित नहीं होगा, बल्कि अन्य डेवलपर्स से भी इसके सदस्यों को जोड़ने से बचें।
mdarefull

@florian leitgeb तब पसंदीदा तरीका है, केवल स्थिर विधियों और / या अमूर्त कीवर्ड वाला एक वर्ग? यह सिर्फ मॉड्यूल की तुलना में भद्दा लगता है जो अब पदावनत लगता है
wired00

182

सार वर्ग टाइपस्क्रिप्ट 1.6 के बाद से टाइपस्क्रिप्ट का प्रथम श्रेणी का नागरिक रहा है। आप एक अमूर्त वर्ग को तात्कालिक नहीं कर सकते।

यहाँ एक उदाहरण है:

export abstract class MyClass {         
    public static myProp = "Hello";

    public static doSomething(): string {
      return "World";
    }
}

const okay = MyClass.doSomething();

//const errors = new MyClass(); // Error

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

1
क्या हम एक सार वर्ग बना सकते हैं?
किम्चमैन

@ किमचीमैन - हाँ, abstractकीवर्ड टाइपस्क्रिप्ट में समर्थित है।
फेंटन

1
का उपयोग करने के लिए अद्यतन abstract! @ किमचीमैन - महान विचार!
ओब्सीडियन

3
क्या यह कंस्ट्रक्टर को निजी के रूप में चिह्नित करने से बेहतर दृष्टिकोण है?
जोरो टेनेव

72

एक वर्ग की स्थैतिक गुणों और विधियों को परिभाषित करना टाइपसेप्ट भाषा विशिष्टता के 8.2.1 में वर्णित है :

class Point { 
  constructor(public x: number, public y: number) { } 
  public distance(p: Point) { 
    var dx = this.x - p.x; 
    var dy = this.y - p.y; 
    return Math.sqrt(dx * dx + dy * dy); 
  } 
  static origin = new Point(0, 0); 
  static distance(p1: Point, p2: Point) { 
    return p1.distance(p2); 
  } 
}

जहाँ Point.distance()एक स्थिर (या "वर्ग") विधि है।


14
इससे पता चलता है कि स्थैतिक विधि कैसे बनाई जाती है , यह उस प्रश्न का उत्तर नहीं देता है जो स्थैतिक वर्गों के बारे में है (जब तक कि वास्तविक प्रश्न वास्तव में स्थैतिक विधियों के बारे में नहीं है)।
मार्कस

18
टिप्पणी के लिए धन्यवाद। यह बताता है कि स्थैतिक गुणों और विधियों का निर्माण कैसे किया जाता है, जो एक साथ लिया जाता है, जिससे किसी को तात्कालिकता की आवश्यकता के बिना डेटा और कार्यक्षमता के साथ एक वर्ग बनाने की अनुमति मिलती है। जबकि विशेष रूप से एक "स्थिर वर्ग" नहीं है, यह ओपी के जावास्क्रिप्ट उदाहरण द्वारा वर्णित आवश्यकता को पूरा करता है।
रॉब रईस

संस्करण 2 तक c # में स्थिर कक्षाएं नहीं थीं। वे c # में ही मौजूद हैं, ताकि आप उन्हें त्वरित रूप से रोक सकें। आप जावास्क्रिप्ट के साथ ऐसा नहीं कर सकते हैं तो इसका बहुत मतलब नहीं है
साइमन_वेचर

4
@Simon_Weaver आप जावास्क्रिप्ट में क्या कर सकते हैं? कक्षाओं को तत्काल रोकें? टाइपस्क्रिप्ट वैसे भी रनटाइम के बारे में ज्यादा परवाह नहीं करती है, जब तक आप एक कंपाइल एरर प्राप्त करते हैं जब आप वह सामान करने की कोशिश करते हैं, जिसकी आपको जरूरत नहीं है।
एलेक्स

मुझे लगता है कि मेरा क्या मतलब था 'हमारे पास कक्षा स्तर पर स्थिर KEYWORD नहीं था (जिसका अर्थ है कि आप एक वर्ग का एक उदाहरण नहीं बना सकते हैं)' संस्करण 2 तक। लेकिन इसे फिर से पढ़ते हुए मुझे लगता है कि मेरी टिप्पणी की तरह याद आती है ' वैसे भी। ओपी वास्तव में पूरी कक्षा के लिए 'स्थिर कीवर्ड' की तलाश नहीं कर रहा था
साइमन_वेवर

20

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

class MyStaticClass {
    public static readonly property: number = 42;
    public static myMethod(): void { /* ... */ }
    private constructor() { /* noop */ }
}

यह स्निपेट आपको केवल नीचे के साथ सी # समकक्ष के समान "स्थिर" कक्षाओं का उपयोग करने की अनुमति देगा कि यह अभी भी अंदर से उन्हें त्वरित करना संभव है। सौभाग्य से यद्यपि आप निजी कंस्ट्रक्टरों के साथ कक्षाएं नहीं बढ़ा सकते।


9

ये एक तरीका है:

class SomeClass {
    private static myStaticVariable = "whatever";
    private static __static_ctor = (() => { /* do static constructor stuff :) */ })();
}

__static_ctorयहाँ एक तुरंत लागू समारोह अभिव्यक्ति है। टाइपस्क्रिप्ट उत्पन्न वर्ग के अंत में इसे कॉल करने के लिए कोड का उत्पादन करेगा।

अपडेट: स्थिर निर्माणकर्ताओं में सामान्य प्रकारों के लिए, जिन्हें अब स्थैतिक सदस्यों द्वारा संदर्भित करने की अनुमति नहीं है, आपको अब अतिरिक्त कदम की आवश्यकता होगी:

class SomeClass<T> {
    static myStaticVariable = "whatever";
    private ___static_ctor = (() => { var someClass:SomeClass<T> ; /* do static constructor stuff :) */ })();
    private static __static_ctor = SomeClass.prototype.___static_ctor();
}

किसी भी मामले में, निश्चित रूप से, आप कक्षा के बाद सामान्य प्रकार के स्थिर निर्माता को कॉल कर सकते हैं , जैसे:

class SomeClass<T> {
    static myStaticVariable = "whatever";
    private __static_ctor = (() => { var example: SomeClass<T>; /* do static constructor stuff :) */ })();
}
SomeClass.prototype.__static_ctor();

बस ऊपर (जाहिर है) thisमें उपयोग करने के लिए याद रखें __static_ctor


इस तरह अभी भी वर्ग के लिए एक निर्माता का उत्सर्जन करता है।
वेसक्लेममॉर्टी

1
"इस तरह" एक हैक है, और उम्मीद के मुताबिक कंपाइलर के सामान्य ऑपरेशन को नहीं बदलता है। यहां तक ​​कि class SomeClass {}एक निर्माता भी उत्पन्न करता है - शायद ही कोई टिप्पणी करने लायक हो, क्योंकि एक नया मुद्दा पेश किया जाता है। ;) FYI करें: JS में कोई वास्तविक "कंस्ट्रक्टर" नहीं हैं - केवल ऐसे फ़ंक्शन हैं जिनके पास ऑब्जेक्ट्स पर या इसके माध्यम से "यह" है new। यह किसी भी "वर्ग" के लिए कोई बात नहीं है।
जेम्स विल्किंस

6

मुझे आज (31/07/2018) को एक ही उपयोग का मामला मिला और इसे वर्कअराउंड पाया। यह मेरे शोध पर आधारित है और इसने मेरे लिए काम किया। उम्मीद - टाइपस्क्रिप्ट में निम्नलिखित प्राप्त करने के लिए:

var myStaticClass = {
    property: 10,
    method: function(){} 
}

इसे मैने किया है:

//MyStaticMembers.ts
namespace MyStaticMembers {
        class MyStaticClass {
           static property: number = 10;
           static myMethod() {...}
        }
        export function Property(): number {
           return MyStaticClass.property;
        }
        export function Method(): void {
           return MyStaticClass.myMethod();
        }
     }

इसलिए हम इसे नीचे के रूप में उपभोग करेंगे:

//app.ts
/// <reference path="MyStaticMembers.ts" />
    console.log(MyStaticMembers.Property);
    MyStaticMembers.Method();

इसने मेरे लिए काम किया। अगर किसी के पास अन्य बेहतर सुझाव हैं तो कृपया हम सभी को सुनने दें !!! धन्यवाद...


3

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

const myStaticClass = {
    property: 10,

    method() {

    }
}

1
क्या यह दृष्टिकोण आपके वर्कफ़्लो को गड़बड़ नहीं करता है? एक तरफ आप कक्षाओं और उदाहरणों का उपयोग करते हैं, और फिर अचानक आप नियमित रूप से पुराने जेएस ऑब्जेक्ट्स में डेटा की घोषणा करना शुरू करते हैं ... स्थैतिक कक्षाओं का उपयोग भी पठनीयता में सहायक होता है, यह केवल भाषा के आंतरिक कामकाज के बारे में नहीं है।
कोकोडको

4
मुझे यह अपने वर्कफ़्लो के साथ खिलवाड़ नहीं लगता; इसके विपरीत, मुझे क्लासलेस JavaScrpit ऑब्जेक्ट या बस सादे फ़ंक्शन और एक मॉड्यूल में स्थिरांक का उपयोग करना बहुत सुविधाजनक लगता है। हालाँकि, मैं यथासंभव वैश्विक स्थिति से बचने की कोशिश करता हूं, इसलिए मुझे शायद ही कभी स्टेटिक क्लास वेरिएबल जैसी किसी चीज की आवश्यकता होती है।
योगू

1

Http://www.basarat.com/2013/04/typescript-static-constructors-for.html देखें

यह एक स्थिर रचनाकार को 'नकली' बनाने का तरीका है। यह इसके खतरों के बिना नहीं है - संदर्भित कोडप्लेक्स आइटम देखें

class Test {
    static foo = "orig";

    // Non void static function
    static stat() {
        console.log("Do any static construction here");
        foo = "static initialized";
        // Required to make function non void
        return null;
    }
    // Static variable assignment
    static statrun = Test.stat();
}

// Static construction will have been done:
console.log(Test.foo);

1

इसे प्राप्त करने का एक संभावित तरीका है कि एक वर्ग का स्थिर उदाहरण दूसरी कक्षा के भीतर हो। उदाहरण के लिए:

class SystemParams
{
  pageWidth:  number = 8270;
  pageHeight: number = 11690;  
}

class DocLevelParams
{
  totalPages: number = 0;
}

class Wrapper
{ 
  static System: SystemParams = new SystemParams();
  static DocLevel: DocLevelParams = new DocLevelParams();
}

फिर व्रपर का उपयोग करके मापदंडों को एक्सेस किया जा सकता है, बिना इसका उदाहरण घोषित किए। उदाहरण के लिए:

Wrapper.System.pageWidth = 1234;
Wrapper.DocLevel.totalPages = 10;

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


1

ES6 बाहरी मॉड्यूल के साथ इसे प्राप्त किया जा सकता है:

// privately scoped array
let arr = [];

export let ArrayModule = {
    add: x => arr.push(x),
    print: () => console.log(arr),
}

यह आंतरिक मॉड्यूल और नेमस्पेस के उपयोग को रोकता है जिसे TSLint [1] [2] द्वारा बुरा व्यवहार माना जाता है , निजी और सार्वजनिक रूप से डांट लगाता है और अवांछित वर्ग वस्तुओं के प्रारंभिककरण को रोकता है।


0

मैं कुछ इसी तरह की खोज कर रहा था और कुछ कहा जाने लगा Singleton Pattern

संदर्भ: सिंगलटन पैटर्न

मैं विभिन्न प्रकार की फ़ाइलों को लोड करने के लिए एक BulkLoader वर्ग पर काम कर रहा हूं और इसके लिए सिंगलटन पैटर्न का उपयोग करना चाहता हूं। इस तरह मैं अपने मुख्य एप्लिकेशन क्लास से फाइलें लोड कर सकता हूं और लोड की गई फाइलों को अन्य कक्षाओं से आसानी से प्राप्त कर सकता हूं।

नीचे एक सरल उदाहरण है कि आप टाइपस्क्रिप्ट और सिंगलटन पैटर्न के साथ गेम के लिए स्कोर मैनेजर कैसे बना सकते हैं।

क्लास सिंगलटनक्लास {

private static _instance:SingletonClass = new SingletonClass();

private _score:number = 0;

constructor() {
    if(SingletonClass._instance){
        throw new Error("Error: Instantiation failed: Use SingletonDemo.getInstance() instead of new.");
    }
    SingletonClass._instance = this;
}

public static getInstance():SingletonClass
{
    return SingletonClass._instance;
}

public setScore(value:number):void
{
    this._score = value;
}

public getScore():number
{
    return this._score;
}

public addPoints(value:number):void
{
    this._score += value;
}

public removePoints(value:number):void
{
    this._score -= value;
}   }

तब कहीं भी आपकी अन्य कक्षाओं में आपको सिंग्लटन तक पहुँच मिलेगी:

var scoreManager = SingletonClass.getInstance();
scoreManager.setScore(10); scoreManager.addPoints(1);
scoreManager.removePoints(2); console.log( scoreManager.getScore() );

0

आप namespaceअपने चर, वर्गों, विधियों को व्यवस्थित करने के लिए भी कीवर्ड का उपयोग कर सकते हैं । डॉक देखें

namespace Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }

    const lettersRegexp = /^[A-Za-z]+$/;
    const numberRegexp = /^[0-9]+$/;

    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }

    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
}

ऊपर फ्लोरियन की टिप्पणी देखें "यह पदावनत है। इसके अलावा tslint आपको मॉड्यूल और नेमस्पेस के लिए अब ऐसा नहीं करने देगा। यहां पढ़ें: palantir.github.io/tslint/rules/no-nameshace"
reggaeguitar
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.