टाइपस्क्रिप्ट में सशर्त प्रकार


65

मैं सोच रहा था कि क्या मैं टाइपस्क्रिप्ट में सशर्त प्रकार हो सकता है?

वर्तमान में मेरे पास निम्न इंटरफ़ेस है:

interface ValidationResult {
  isValid: boolean;
  errorText?: string;
}

लेकिन मैं निकालना चाहते हैं errorText, और जब केवल यह है isValidहै falseएक के रूप में आवश्यक संपत्ति।

काश मैं इसे निम्नलिखित इंटरफ़ेस के रूप में लिखने में सक्षम था:

interface ValidationResult {
  isValid: true;
}

interface ValidationResult {
  isValid: false;
  errorText: string;
}

लेकिन जैसा कि आप जानते हैं, यह संभव नहीं है। तो, इस स्थिति के बारे में आपका क्या विचार है?


क्या आपका मतलब है, कब isValidहै false?
— निश्चितप्रक्रिया

18
isValid तो बेमानी है। आप के रूप में अच्छी तरह से सिर्फ errorText हो सकता है, और फिर अगर errorText शून्य है, तो कोई त्रुटि नहीं है।
— रात को

हाँ, @ बंद, आप सही हैं, लेकिन हमें अपने विरासत कोड के कारण इसे रखना होगा।
— अरमान

जवाबों:


89

इस तरह के तर्क को मॉडल करने का एक तरीका यूनियन प्रकार का उपयोग करना है, कुछ इस तरह से

interface Valid {
  isValid: true
}

interface Invalid {
  isValid: false
  errorText: string
}

type ValidationResult = Valid | Invalid

const validate = (n: number): ValidationResult => {
  return n === 4 ? { isValid: true } : { isValid: false, errorText: "num is not 4" }
}

कंपाइलर तब बूलियन ध्वज के आधार पर प्रकार को कम करने में सक्षम होता है

const getErrorTextIfPresent = (r: ValidationResult): string | null => {
  return r.isValid ? null : r.errorText
}

7
अच्छा उत्तर। और आकर्षक है कि संकलक वास्तव में बता rसकता है कि Invalidयहां प्रकार का होना चाहिए ।
— 10

1
इसे विवेकहीन संघ कहा जाता है। बहुत अच्छा सामान: टाइपस्क्रिप्ट
— lang.org/docs/handbook/…

41

कई इंटरफेस बनाने से बचने के लिए जिन्हें केवल एक तिहाई बनाने की आदत है, आप typeइसके बजाय सीधे वैकल्पिक भी कर सकते हैं :

type ValidationResult = {
    isValid: false;
    errorText: string;
} | {
    isValid: true;
};

20

बग्स द्वारा प्रदर्शित यूनियन यह बताती है कि मैं इससे निपटने की सलाह कैसे देता हूं। बहरहाल, टाइपप्रति है के रूप में जाना कुछ है " सशर्त प्रकार ," और वे इस संभाल कर सकते हैं।

type ValidationResult<IsValid extends boolean = boolean> = (IsValid extends true
    ? { isValid: IsValid; }
    : { isValid: IsValid; errorText: string; }
);


declare const validation: ValidationResult;
if (!validation.isValid) {
    validation.errorText;
}

यह ValidationResult(जो वास्तव में है ValidationResult<boolean>डिफ़ॉल्ट पैरामीटर के कारण) संघ कीड़े के जवाब में या में उत्पादन के बराबर है CertainPerformance के जवाब , और उसी तरीके से उपयोग किया जा सकता है।

यहां लाभ यह है कि आप एक ज्ञात ValidationResult<false>मूल्य के आसपास से गुजर सकते हैं , और फिर आपको परीक्षण नहीं करना होगा isValidक्योंकि यह ज्ञात होगा falseऔर errorStringअस्तित्व के लिए जाना जाएगा। संभवतः इस तरह के मामले के लिए आवश्यक नहीं है - और सशर्त प्रकार जटिल और डीबग करना मुश्किल हो सकते हैं, इसलिए उन्हें संभवतः अनावश्यक रूप से उपयोग नहीं किया जाना चाहिए। लेकिन आप कर सकते हैं, और यह ध्यान देने योग्य था।


3
मुझे यकीन है कि ये कई बार मददगार होते हैं। लेकिन, मेरे लिए, वाक्यविन्यास वास्तव में बुरा लग रहा है।
— Peilonrayz

3
@Peilonrayz एह, यह अन्य टाइपस्क्रिप्ट कोडिंग के साथ अच्छी स्थिरता है, और extendsउपयोग करने के लिए सही ऑपरेटर है। और यह बहुत शक्तिशाली है, खासकर जब से आप इसे प्रकारों में खोदने के लिए भी उपयोग कर सकते हैं type SecondOf<T> = T extends Pair<any, infer U> ? U : never;:।
— KRyan

@KRyan मैं उस बारे में सोच रहा हूँ। क्या इसका मूल अर्थ सिर्फ SecondOf<number>'विस्तार' है Pair<any, number>? मुझे लगता है कि यह कहना कि "एक किताब को कवर करके जज न करें" यहाँ उचित है।
— Peilonrayz

@Peilonrayz आह, नहीं; बल्कि इसके विपरीत। SecondOf<Pair<any, number>>का मूल्यांकन करता है number। SecondOf<number>का मूल्यांकन करता है never, क्योंकि number extends Pair<any, infer U>झूठा है, जैसा numberकि कोई भी विस्तार नहीं करता हैPair
— केरान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.