2016-03-02 13 views
13

क्या JSON से तारों के साथ टाइपस्क्रिप्ट एनम संगत होने का कोई तरीका है?JSON स्ट्रिंग से टाइपस्क्रिप्ट `enum`

उदाहरण के लिए:

enum Type { NEW, OLD } 

interface Thing { type: Type } 

let thing:Thing = JSON.parse('{"type": "NEW"}'); 

alert(thing.type == Type.NEW); // false 

मैं thing.type == Type.NEW तरह सच होना होगा। या अधिक विशेष रूप से, मेरी इच्छा है कि मैं enum मानों को स्ट्रिंग्स के रूप में परिभाषित करने के लिए निर्दिष्ट कर सकता हूं, संख्याओं पर नहीं।

मुझे पता है कि मैं thing.type.toString() == Type[Type.NEW] उपयोग कर सकते हैं कर रहा हूँ, लेकिन यह बोझिल है और enum प्रकार एनोटेशन भ्रामक और गुमराह करने वाला बनाने के लिए है, जो अपने उद्देश्य धरा लगता है। JSON तकनीकी रूप से मान्य एनम मान की आपूर्ति नहीं कर रहा है, इसलिए मुझे संपत्ति को enum में टाइप नहीं करना चाहिए।

तो क्या मैं इस समय के बजाय कर रहा हूँ स्थिर स्थिरांक के साथ एक स्ट्रिंग प्रकार उपयोग कर रहा है:

const Type = { NEW: "NEW", OLD: "OLD" } 

interface Thing { type: string } 

let thing:Thing = JSON.parse('{"type": "NEW"}'); 

alert(thing.type == Type.NEW); // true 

यह मैं उपयोग मैं चाहता हूँ हो जाता है, लेकिन प्रकार एनोटेशन string रास्ता काफ़ी व्यापक है और त्रुटियों की संभावना है।

मुझे आश्चर्य है कि जावास्क्रिप्ट के सुपरसेट में स्ट्रिंग आधारित enums नहीं है। क्या मैं कुछ भूल रहा हूँ? क्या यह अलग तरीके से किया जा सकता है?


अद्यतन टीएस 1,8

एक और विकल्प (धन्यवाद @basaret) string literal types का उपयोग करना है, लेकिन वांछित enum की तरह उपयोग (ऊपर) इसे दो बार अपने मूल्यों को परिभाषित करने की आवश्यकता है प्राप्त करने के लिए: एक बार में एक स्ट्रिंग शाब्दिक प्रकार, और एक बार (निरंतर या नाम स्थान) एक मूल्य के रूप में:

type Type = "NEW" | "OLD"; 
const Type = { 
    NEW: "NEW" as Type, 
    OLD: "OLD" as Type 
} 

interface Thing { type: Type } 

let thing:Thing = JSON.parse(`{"type": "NEW"}`); 

alert(thing.type === Type.NEW); // true 

यह काम करता है लेकिन बॉयलरप्लेट का एक बहुत लेता है, पर्याप्त है कि मैं यह सबसे का उपयोग नहीं करते ओ एफ समय। अभी के लिए मुझे उम्मीद है कि proposal for string enums अंततः रोडमैप बना देगा।


अद्यतन टीएस 2,1

नई keyof type lookup स्ट्रिंग शाब्दिक प्रकार एक स्थिरांक या नाम स्थान है, जो परिभाषा एक थोड़ा कम निरर्थक बना देता है की चाबी से उत्पन्न किया जा करने के लिए अनुमति देता है:

namespace Type { 
    export const OLD = "OLD"; 
    export const NEW = "NEW"; 
} 
type Type = keyof typeof Type; 

interface Thing { type: Type } 

const thing: Thing = JSON.parse('{"type": "NEW"}'); 
thing.type == Type.NEW // true 

अद्यतन टी एस 2.4

TypeScript 2.4 added support for string enums!ऊपर के उदाहरण हो जाता है:

enum Type { 
    OLD = "OLD", 
    NEW = "NEW" 
} 

interface Thing { type: Type } 
const thing: Thing = JSON.parse('{"type": "NEW"}'); 
alert(thing.type == Type.NEW) // true 

यह लगभग सही है, लेकिन अभी भी कुछ गहन खिन्नता है:

  • आप अभी भी, दो बार मूल्य लिखने के लिए यानी OLD = "OLD" है, और वहाँ कोई मान्यता है कि आपके पास टाइपो नहीं है, जैसे NEW = "MEW" ... यह पहले से ही मुझे वास्तविक कोड में काट चुका है।
  • कुछ विषमताएं हैं (शायद बग?) कैसे enum टाइप की गई है, यह केवल एक स्ट्रिंग शाब्दिक प्रकार शॉर्टेंड नहीं है, जो वास्तव में सही होगा। कुछ मुद्दों मैं टकरा गया है:

    enum Color { RED = "RED", BLUE = "BLUE", GREEN = "GREEN" } 
    
    type ColorMap = { [P in Color]: number; } 
    
    declare const color: Color; 
    declare const map: ColorMap; 
    map[color] // Error: Element implicitly has an 'any' type because type 'ColorMap' has no index signature. 
    
    const red: Color = "RED"; // Type '"RED"' is not assignable to type 'Color'. 
    const blue: Color = "BLUE" as "RED" | "BLUE" | "GREEN"; // Error: Type '"RED" | "BLUE" | "GREEN"' is not assignable to type 'Color'. 
    

    enum Color साथ बराबर कोड स्ट्रिंग शाब्दिक प्रकार ठीक से काम द्वारा बदल दिया ...

हाँ, मुझे लगता है कि मैं इस बारे में ओसीडी है, मैं बस चाहता हूँ मेरा सही जेएस enums। :)

उत्तर

6

आप 2.4 रिलीज होने से पहले टाइपप्रति उपयोग कर रहे हैं, वहाँ enums के साथ कि प्राप्त करने के लिए any करने के लिए अपने enum के मूल्यों कास्टिंग द्वारा एक तरीका है।

एक example of your first implementation

enum Type { 
    NEW = <any>"NEW", 
    OLD = <any>"OLD", 
} 

interface Thing { type: Type } 

let thing:Thing = JSON.parse('{"type": "NEW"}'); 

alert(thing.type == Type.NEW); // true 

पहले से ही Typescript 2.4 has built in support for string enums, तो any को कास्ट नहीं रह गया है आवश्यक हो सकता है और आप String Literal Union Type का उपयोग, जो सत्यापन और स्वत: पूर्ण के लिए ठीक है बिना इसे हासिल कर सकता है, लेकिन के लिए इतना अच्छा नहीं उपयोग परिदृश्य के आधार पर पठनीयता और रिफैक्टरिंग।

+0

धन्यवाद! काश मैं पहले किसी भी 'दावा' के बारे में पता था। अब, मैं टीएस 2 कोशिश कर रहा हूँ।4 स्ट्रिंग एम्स, और यह मूल रूप से जो चाहता था उसके करीब है ... लेकिन मुझे टीएस प्रकार की जांच के तरीके के साथ कुछ समस्याएं मिली हैं ... – Aaron

+0

@Aaron शांत, मदद करने में खुशी! साथ ही, आप [ts-enums] (https://github.com/LMFinney/ts-enums) प्रोजेक्ट को जांचना चाहेंगे क्योंकि यह कई उपयोग मामलों के लिए बहुत बहुमुखी और शक्तिशाली enum हैंडलिंग बनाता है –

0

लेकिन टाइप एनोटेशन स्ट्रिंग रास्ता बहुत व्यापक और त्रुटि प्रवण है।

सहमत हुए। एक त्वरित समाधान का (यदि आप कोड पीढ़ी के लक्जरी है कि आप इस स्वचालित कर सकते हैं):

interface Thing { type: "NEW" | "OLD" } 

ये एक संघ में स्ट्रिंग शाब्दिक कहा जाता है। अधिक: https://basarat.gitbooks.io/typescript/content/docs/tips/stringEnums.html

+0

यह आशाजनक लग रहा है। जब हम टीएस 1.8 में अपग्रेड करेंगे तो हम जांच करेंगे। मैं इसके साथ खेल रहा था और स्ट्रिंग अक्षर मूल्यों को स्थिरांक के रूप में उपयोग करने में सक्षम नहीं था, यानी 'thing.type == Type.NEW' जैसी कुछ। – Aaron

+1

[यह जितना करीब हो सकता है] (http://www.typescriptlang.org/Playground#src=type%20Type%20%3D%20%22NEW%22%20%7C%20%22OLD%22% 3 बी% 0Aconst% 20Type% 20% 3 डी% 20% 7B% 0A% 09NEW% 3A% 20% 22NEW% 22% 2C% 0A% 09OLD% 3A% 20% 22OLD% 22% 0A% 7 दिन% 0A% 0Ainterface% 20Thing% 20% 7B% 20type% 3A% 20Type% 20% 7 दिन% 0A% 0Alet% 20thing% 3AThing% 20% 3 डी% 20JSON.parse (% से 60% 7 बी% 22type% 22% 3 ए% 20% 22NEW% 22% 60% से 7 दिन)% 3 बी% 0 ए% 0 अलर्ट (thing.type% 20% 3 डी% 3 डी% 3 डी% 20 टाइप टाइप।%)% 3 बी), लेकिन इसे 'टाइप' और मानों को दो बार परिभाषित करने की आवश्यकता है, एक बार' टाइप 'के रूप में उपयोग के लिए एक इंटरफेस प्रकार एनोटेशन, और फिर उन उपयोगों के लिए 'const' के रूप में जहां मुझे मूल्यों की आवश्यकता होती है। क्या यह सुधार किया जा सकता है? – Aaron

0

मैं एक स्टॉपगैप के रूप में कनवर्टर कार्यों का उपयोग कर रहा हूं। उम्मीद है कि इस सूत्र एक संकल्प की बात आती है: https://github.com/Microsoft/TypeScript/issues/1206

enum ErrorCode { 
    Foo, 
    Bar 
} 

interface Error { 
    code: ErrorCode; 
    message?: string; 
} 

function convertToError(obj: any): Error { 
    let typed: Error = obj as Error; 

    // Fix any enums 
    typed.code = ErrorCode[typed.code.toString()]; 
    return typed; 
} 
संबंधित मुद्दे