टाइपस्क्रिप्ट जावास्क्रिप्ट के शीर्ष पर निर्मित एक दृढ़ता से टाइप की गई प्रोग्रामिंग भाषा होने का दावा करती है, जो किसी भी पैमाने पर बेहतर टूलिंग प्रदान करती है। हालाँकि, टाइपस्क्रिप्ट में any
प्रकार शामिल होता है, जो अक्सर कोडबेस में अंतर्निहित रूप से घुस सकता है और टाइपस्क्रिप्ट के कई लाभों को खो सकता है।
यह आलेख टाइपस्क्रिप्ट परियोजनाओं में any
प्रकार का नियंत्रण लेने के तरीकों की पड़ताल करता है। टाइपस्क्रिप्ट की शक्ति को उजागर करने, सर्वोत्तम प्रकार की सुरक्षा प्राप्त करने और कोड गुणवत्ता में सुधार करने के लिए तैयार हो जाइए।
टाइपस्क्रिप्ट डेवलपर अनुभव और उत्पादकता को बढ़ाने के लिए अतिरिक्त टूलींग की एक श्रृंखला प्रदान करता है:
हालाँकि, जैसे ही आप अपने कोडबेस में any
प्रकार का उपयोग करना शुरू करते हैं, आप ऊपर सूचीबद्ध सभी लाभ खो देते हैं। any
प्रकार की प्रणाली में कोई भी प्रकार एक खतरनाक खामी है, और इसका उपयोग सभी प्रकार-जांच क्षमताओं के साथ-साथ सभी टूलींग को अक्षम कर देता है जो प्रकार-जाँच पर निर्भर करता है। परिणामस्वरूप, टाइपस्क्रिप्ट के सभी लाभ खो जाते हैं: बग छूट जाते हैं, कोड संपादक कम उपयोगी हो जाते हैं, और भी बहुत कुछ।
उदाहरण के लिए, निम्नलिखित उदाहरण पर विचार करें:
function parse(data: any) { return data.split(''); } // Case 1 const res1 = parse(42); // ^ TypeError: data.split is not a function // Case 2 const res2 = parse('hello'); // ^ any
उपरोक्त कोड में:
parse
फ़ंक्शन के अंदर स्वत: पूर्णता से चूक जाएंगे। जब आप data.
आपके संपादक में, आपको data
के लिए उपलब्ध तरीकों के लिए सही सुझाव नहीं दिए जाएंगे।TypeError: data.split is not a function
क्योंकि हमने एक स्ट्रिंग के बजाय एक संख्या पास की है। टाइपस्क्रिप्ट त्रुटि को उजागर करने में सक्षम नहीं है क्योंकि any
प्रकार की जाँच अक्षम कर देता है।res2
वेरिएबल का भी any
प्रकार होता है। इसका मतलब यह है कि any
के एक बार उपयोग से कोडबेस के बड़े हिस्से पर व्यापक प्रभाव पड़ सकता है।
any
उपयोग केवल चरम मामलों में या प्रोटोटाइप आवश्यकताओं के लिए ठीक है। सामान्य तौर पर, टाइपस्क्रिप्ट से अधिकतम लाभ प्राप्त करने के लिए any
उपयोग करने से बचना बेहतर है।
कोडबेस में any
प्रकार के स्रोतों के बारे में जागरूक होना महत्वपूर्ण है क्योंकि any
स्पष्ट रूप से लिखना एकमात्र विकल्प नहीं है। any
प्रकार के उपयोग से बचने के हमारे सर्वोत्तम प्रयासों के बावजूद, यह कभी-कभी कोडबेस में अप्रत्यक्ष रूप से घुस सकता है।
कोडबेस में any
प्रकार के चार मुख्य स्रोत होते हैं:
any
का स्पष्ट उपयोग।
मैंने पहले दो बिंदुओं के लिए tsconfig में मुख्य बातों और मानक लाइब्रेरी प्रकारों में सुधार पर पहले ही लेख लिखा है। यदि आप अपनी परियोजनाओं में प्रकार की सुरक्षा में सुधार करना चाहते हैं तो कृपया उनकी जाँच करें।
इस बार, हम कोडबेस में any
प्रकार की उपस्थिति को नियंत्रित करने के लिए स्वचालित टूल पर ध्यान केंद्रित करेंगे।
ESLint एक लोकप्रिय स्थैतिक विश्लेषण उपकरण है जिसका उपयोग वेब डेवलपर्स द्वारा सर्वोत्तम प्रथाओं और कोड स्वरूपण को सुनिश्चित करने के लिए किया जाता है। इसका उपयोग कोडिंग शैलियों को लागू करने और ऐसे कोड ढूंढने के लिए किया जा सकता है जो कुछ दिशानिर्देशों का पालन नहीं करते हैं।
ESLint का उपयोग टाइपस्क्रिप्ट प्रोजेक्ट्स के साथ भी किया जा सकता है, typectipt-eslint प्लगइन के लिए धन्यवाद। सबसे अधिक संभावना है, यह प्लगइन आपके प्रोजेक्ट में पहले ही इंस्टॉल हो चुका है। लेकिन यदि नहीं, तो आप आधिकारिक शुरुआत मार्गदर्शिका का अनुसरण कर सकते हैं।
typescript-eslint
के लिए सबसे सामान्य कॉन्फ़िगरेशन इस प्रकार है:
module.exports = { extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', ], plugins: ['@typescript-eslint'], parser: '@typescript-eslint/parser', root: true, };
यह कॉन्फ़िगरेशन eslint
सिंटैक्स स्तर पर टाइपस्क्रिप्ट को समझने में सक्षम बनाता है, जिससे आप सरल एस्लिंट नियम लिख सकते हैं जो कोड में मैन्युअल रूप से लिखे गए प्रकारों पर लागू होते हैं। उदाहरण के लिए, आप any
के स्पष्ट उपयोग पर रोक लगा सकते हैं।
recommended
प्रीसेट में कोड शुद्धता में सुधार लाने के उद्देश्य से ESLint नियमों का सावधानीपूर्वक चयनित सेट शामिल है। हालाँकि इस लेख के प्रयोजन के लिए संपूर्ण प्रीसेट का उपयोग करने की अनुशंसा की जाती है, हम केवल no-explicit-any
नियम पर ध्यान केंद्रित करेंगे।
टाइपस्क्रिप्ट का सख्त मोड निहित any
के उपयोग को रोकता है, लेकिन यह any
स्पष्ट रूप से उपयोग करने से नहीं रोकता है। no-explicit-any
नियम कोडबेस में any
भी मैन्युअल रूप से लिखने पर रोक लगाने में मदद करता है।
// ❌ Incorrect function loadPokemons(): any {} // ✅ Correct function loadPokemons(): unknown {} // ❌ Incorrect function parsePokemons(data: Response<any>): Array<Pokemon> {} // ✅ Correct function parsePokemons(data: Response<unknown>): Array<Pokemon> {} // ❌ Incorrect function reverse<T extends Array<any>>(array: T): T {} // ✅ Correct function reverse<T extends Array<unknown>>(array: T): T {}
इस नियम का प्राथमिक उद्देश्य पूरी टीम में any
के भी प्रयोग को रोकना है। यह टीम के इस समझौते को मजबूत करने का एक साधन है कि परियोजना में any
के भी उपयोग को हतोत्साहित किया जाता है।
यह एक महत्वपूर्ण लक्ष्य है क्योंकि any
के एक भी उपयोग से प्रकार के अनुमान के कारण कोडबेस के एक महत्वपूर्ण हिस्से पर व्यापक प्रभाव पड़ सकता है। हालाँकि, यह अभी भी अंतिम प्रकार की सुरक्षा प्राप्त करने से बहुत दूर है।
हालाँकि हमने स्पष्ट रूप से उपयोग किए गए any
से निपटा है, फिर भी किसी परियोजना की निर्भरता के भीतर अभी भी कई निहित हैं, जिनमें एनपीएम पैकेज और टाइपस्क्रिप्ट की मानक लाइब्रेरी शामिल हैं any
निम्नलिखित कोड पर विचार करें, जो किसी भी प्रोजेक्ट में देखे जाने की संभावना है:
const response = await fetch('https://pokeapi.co/api/v2/pokemon'); const pokemons = await response.json(); // ^? any const settings = JSON.parse(localStorage.getItem('user-settings')); // ^? any
दोनों वैरिएबल pokemons
और settings
परोक्ष रूप से any
प्रकार दिया गया था। इस मामले में न तो no-explicit-any
और न ही टाइपस्क्रिप्ट का सख्त मोड हमें चेतावनी देगा। अभी तक नहीं।
ऐसा इसलिए होता है क्योंकि response.json()
और JSON.parse()
के प्रकार टाइपस्क्रिप्ट की मानक लाइब्रेरी से आते हैं, जहां इन विधियों में स्पष्ट रूप से any
एनोटेशन होता है। हम अभी भी अपने वेरिएबल्स के लिए मैन्युअल रूप से एक बेहतर प्रकार निर्दिष्ट कर सकते हैं, लेकिन मानक लाइब्रेरी में any
की लगभग 1,200 घटनाएँ हैं। उन सभी मामलों को याद रखना लगभग असंभव है जहां any
मानक लाइब्रेरी से हमारे कोडबेस में घुस सकता है।
बाहरी निर्भरता के लिए भी यही बात लागू होती है। एनपीएम में कई खराब टाइप की गई लाइब्रेरी हैं, जिनमें से अधिकांश अभी भी जावास्क्रिप्ट में लिखी जा रही हैं। परिणामस्वरूप, ऐसे पुस्तकालयों का उपयोग करने से आसानी से कोडबेस में बहुत any
अंतर्निहित हो सकता है।
आम तौर पर, हमारे कोड में any
करने के लिए अभी भी कई तरीके हैं।
आदर्श रूप से, हम टाइपस्क्रिप्ट में एक ऐसी सेटिंग रखना चाहेंगे जो कंपाइलर को किसी भी वेरिएबल के बारे में शिकायत करने पर मजबूर कर दे, जिसे किसी भी कारण से any
प्रकार प्राप्त हुआ हो। दुर्भाग्य से, ऐसी कोई सेटिंग वर्तमान में मौजूद नहीं है और इसे जोड़े जाने की उम्मीद नहीं है।
हम typescript-eslint
प्लगइन के टाइप-चेक मोड का उपयोग करके इस व्यवहार को प्राप्त कर सकते हैं। यह मोड टाइपस्क्रिप्ट कंपाइलर से ESLint नियमों तक संपूर्ण प्रकार की जानकारी प्रदान करने के लिए टाइपस्क्रिप्ट के साथ मिलकर काम करता है। इस जानकारी के साथ, अधिक जटिल ESLint नियम लिखना संभव है जो अनिवार्य रूप से टाइपस्क्रिप्ट की टाइप-चेकिंग क्षमताओं का विस्तार करते हैं। उदाहरण के लिए, एक नियम any
प्रकार के सभी चर पा सकता है, भले ही any
कैसे प्राप्त किया गया हो।
टाइप-अवेयर नियमों का उपयोग करने के लिए, आपको ESLint कॉन्फ़िगरेशन को थोड़ा समायोजित करने की आवश्यकता है:
module.exports = { extends: [ 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-type-checked', ], plugins: ['@typescript-eslint'], parser: '@typescript-eslint/parser', + parserOptions: { + project: true, + tsconfigRootDir: __dirname, + }, root: true, };
typescript-eslint
के लिए प्रकार अनुमान को सक्षम करने के लिए, ESLint कॉन्फ़िगरेशन में parserOptions
जोड़ें। फिर, recommended
प्रीसेट को recommended-type-checked
से बदलें। बाद वाला प्रीसेट लगभग 17 नए शक्तिशाली नियम जोड़ता है। इस लेख के प्रयोजन के लिए, हम उनमें से केवल 5 पर ध्यान केंद्रित करेंगे।
no-unsafe-argument
नियम फ़ंक्शन कॉल की खोज करता है जिसमें any
प्रकार का एक चर पैरामीटर के रूप में पारित किया जाता है। जब ऐसा होता है, तो टाइप-चेकिंग ख़त्म हो जाती है, और मजबूत टाइपिंग के सभी लाभ भी ख़त्म हो जाते हैं।
उदाहरण के लिए, आइए एक saveForm
फ़ंक्शन पर विचार करें जिसके लिए पैरामीटर के रूप में एक ऑब्जेक्ट की आवश्यकता होती है। मान लीजिए कि हम JSON प्राप्त करते हैं, इसे पार्स करते हैं, और any
प्रकार प्राप्त करते हैं।
// ❌ Incorrect function saveForm(values: FormValues) { console.log(values); } const formValues = JSON.parse(userInput); // ^? any saveForm(formValues); // ^ Unsafe argument of type `any` assigned // to a parameter of type `FormValues`.
जब हम इस पैरामीटर के साथ saveForm
फ़ंक्शन को कॉल करते हैं, no-unsafe-argument
नियम इसे असुरक्षित के रूप में चिह्नित करता है और हमें value
चर के लिए उचित प्रकार निर्दिष्ट करने की आवश्यकता होती है।
यह नियम फ़ंक्शन तर्कों के भीतर नेस्टेड डेटा संरचनाओं का गहराई से निरीक्षण करने के लिए पर्याप्त शक्तिशाली है। इसलिए, आप निश्चिंत हो सकते हैं कि ऑब्जेक्ट को फ़ंक्शन तर्क के रूप में पास करने पर कभी भी अनटाइप किया गया डेटा नहीं होगा।
// ❌ Incorrect saveForm({ name: 'John', address: JSON.parse(addressJson), // ^ Unsafe assignment of an `any` value. });
त्रुटि को ठीक करने का सबसे अच्छा तरीका टाइपस्क्रिप्ट के प्रकार को सीमित करना या ज़ॉड या सुपरस्ट्रक्चर जैसी सत्यापन लाइब्रेरी का उपयोग करना है। उदाहरण के लिए, आइए parseFormValues
फ़ंक्शन लिखें जो पार्स किए गए डेटा के सटीक प्रकार को सीमित करता है।
// ✅ Correct function parseFormValues(data: unknown): FormValues { if ( typeof data === 'object' && data !== null && 'name' in data && typeof data['name'] === 'string' && 'address' in data && typeof data.address === 'string' ) { const { name, address } = data; return { name, address }; } throw new Error('Failed to parse form values'); } const formValues = parseFormValues(JSON.parse(userInput)); // ^? FormValues saveForm(formValues);
ध्यान दें कि unknown
को स्वीकार करने वाले फ़ंक्शन में any
प्रकार को तर्क के रूप में पारित करने की अनुमति है, क्योंकि ऐसा करने से जुड़ी कोई सुरक्षा चिंताएं नहीं हैं।
डेटा सत्यापन फ़ंक्शन लिखना एक कठिन काम हो सकता है, खासकर जब बड़ी मात्रा में डेटा से निपटना हो। इसलिए, डेटा सत्यापन लाइब्रेरी के उपयोग पर विचार करना उचित है। उदाहरण के लिए, ज़ॉड के साथ, कोड इस तरह दिखेगा:
// ✅ Correct import { z } from 'zod'; const schema = z.object({ name: z.string(), address: z.string(), }); const formValues = schema.parse(JSON.parse(userInput)); // ^? { name: string, address: string } saveForm(formValues);
no-unsafe-assignment
नियम वेरिएबल असाइनमेंट की खोज करता है जिसमें किसी मान का any
प्रकार होता है। ऐसे असाइनमेंट कंपाइलर को यह सोचने में गुमराह कर सकते हैं कि एक वेरिएबल का एक निश्चित प्रकार होता है, जबकि डेटा का वास्तव में एक अलग प्रकार हो सकता है।
JSON पार्सिंग के पिछले उदाहरण पर विचार करें:
// ❌ Incorrect const formValues = JSON.parse(userInput); // ^ Unsafe assignment of an `any` value
no-unsafe-assignment
नियम के लिए धन्यवाद, हम formValues
कहीं और पास करने से पहले भी any
प्रकार को पकड़ सकते हैं। फिक्सिंग रणनीति वही रहती है: हम वेरिएबल के मान को एक विशिष्ट प्रकार प्रदान करने के लिए प्रकार संकुचन का उपयोग कर सकते हैं।
// ✅ Correct const formValues = parseFormValues(JSON.parse(userInput)); // ^? FormValues
ये दोनों नियम बहुत कम बार ट्रिगर होते हैं। हालाँकि, मेरे अनुभव के आधार पर, जब आप खराब टाइप की गई तृतीय-पक्ष निर्भरता का उपयोग करने का प्रयास कर रहे हों तो वे वास्तव में सहायक होते हैं।
no-unsafe-member-access
नियम हमें ऑब्जेक्ट गुणों तक पहुंचने से रोकता है यदि किसी वेरिएबल में any
प्रकार है, क्योंकि यह null
या undefined
हो सकता है।
no-unsafe-call
नियम हमें any
प्रकार के वेरिएबल को फ़ंक्शन के रूप में कॉल करने से रोकता है, क्योंकि यह एक फ़ंक्शन नहीं हो सकता है।
आइए कल्पना करें कि हमारे पास एक खराब टाइप की गई तृतीय-पक्ष लाइब्रेरी है जिसे untyped-auth
कहा जाता है:
// ❌ Incorrect import { authenticate } from 'untyped-auth'; // ^? any const userInfo = authenticate(); // ^? any ^ Unsafe call of an `any` typed value. console.log(userInfo.name); // ^ Unsafe member access .name on an `any` value.
लिंटर दो मुद्दों पर प्रकाश डालता है:
authenticate
फ़ंक्शन को कॉल करना असुरक्षित हो सकता है, क्योंकि हम फ़ंक्शन में महत्वपूर्ण तर्क पारित करना भूल सकते हैं।userInfo
ऑब्जेक्ट से name
प्रॉपर्टी को पढ़ना असुरक्षित है, क्योंकि प्रमाणीकरण विफल होने पर यह null
हो जाएगा।
इन त्रुटियों को ठीक करने का सबसे अच्छा तरीका दृढ़ता से टाइप की गई एपीआई वाली लाइब्रेरी का उपयोग करने पर विचार करना है। लेकिन यदि यह कोई विकल्प नहीं है, तो आपलाइब्रेरी प्रकारों को स्वयं बढ़ा सकते हैं। निश्चित लाइब्रेरी प्रकारों वाला एक उदाहरण इस तरह दिखेगा:
// ✅ Correct import { authenticate } from 'untyped-auth'; // ^? (login: string, password: string) => Promise<UserInfo | null> const userInfo = await authenticate('test', 'pwd'); // ^? UserInfo | null if (userInfo) { console.log(userInfo.name); }
no-unsafe-return
नियम किसी फ़ंक्शन से any
प्रकार को गलती से वापस नहीं लौटाने में मदद करता है, जिसे कुछ अधिक विशिष्ट लौटाना चाहिए। ऐसे मामले कंपाइलर को यह सोचने में गुमराह कर सकते हैं कि लौटाए गए मान का एक निश्चित प्रकार है, जबकि डेटा का वास्तव में एक अलग प्रकार हो सकता है।
उदाहरण के लिए, मान लीजिए कि हमारे पास एक फ़ंक्शन है जो JSON को पार्स करता है और दो गुणों के साथ एक ऑब्जेक्ट लौटाता है।
// ❌ Incorrect interface FormValues { name: string; address: string; } function parseForm(json: string): FormValues { return JSON.parse(json); // ^ Unsafe return of an `any` typed value. } const form = parseForm('null'); console.log(form.name); // ^ TypeError: Cannot read properties of null
parseForm
फ़ंक्शन प्रोग्राम के किसी भी हिस्से में रनटाइम त्रुटियों का कारण बन सकता है जहां इसका उपयोग किया जाता है, क्योंकि पार्स किए गए मान की जांच नहीं की जाती है। no-unsafe-return
नियम ऐसे रनटाइम मुद्दों को रोकता है।
यह सुनिश्चित करने के लिए सत्यापन जोड़कर इसे ठीक करना आसान है कि पार्स किया गया JSON अपेक्षित प्रकार से मेल खाता है। आइए इस बार ज़ॉड लाइब्रेरी का उपयोग करें:
// ✅ Correct import { z } from 'zod'; const schema = z.object({ name: z.string(), address: z.string(), }); function parseForm(json: string): FormValues { return schema.parse(JSON.parse(json)); }
टाइप-चेक किए गए नियमों का उपयोग करना ESLint के लिए प्रदर्शन दंड के साथ आता है क्योंकि इसे सभी प्रकारों का अनुमान लगाने के लिए टाइपस्क्रिप्ट के कंपाइलर को लागू करना होगा। यह मंदी मुख्य रूप से प्री-कमिट हुक और सीआई में लिंटर चलाते समय ध्यान देने योग्य है, लेकिन आईडीई में काम करते समय यह ध्यान देने योग्य नहीं है। प्रकार की जाँच आईडीई स्टार्टअप पर एक बार की जाती है और फिर जैसे ही आप कोड बदलते हैं, प्रकार अपडेट हो जाते हैं।
यह ध्यान देने योग्य है कि केवल प्रकारों का अनुमान लगाना tsc
कंपाइलर के सामान्य आह्वान की तुलना में तेजी से काम करता है। उदाहरण के लिए, टाइपस्क्रिप्ट कोड की लगभग 1.5 मिलियन लाइनों के साथ हमारे सबसे हालिया प्रोजेक्ट पर, tsc
के माध्यम से टाइप चेकिंग में लगभग 11 मिनट लगते हैं, जबकि ESLint के टाइप-अवेयर नियमों को बूटस्ट्रैप करने के लिए आवश्यक अतिरिक्त समय केवल 2 मिनट है।
हमारी टीम के लिए, प्रकार-जागरूक स्थैतिक विश्लेषण नियमों का उपयोग करके प्रदान की गई अतिरिक्त सुरक्षा व्यापार के लायक है। छोटी परियोजनाओं पर, यह निर्णय लेना और भी आसान है।
इष्टतम प्रकार की सुरक्षा और कोड गुणवत्ता प्राप्त करने के लिए टाइपस्क्रिप्ट परियोजनाओं में any
के उपयोग को नियंत्रित करना महत्वपूर्ण है। typescript-eslint
प्लगइन का उपयोग करके, डेवलपर्स अपने कोडबेस में any
प्रकार की किसी भी घटना को पहचान और समाप्त कर सकते हैं, जिसके परिणामस्वरूप एक अधिक मजबूत और रखरखाव योग्य कोडबेस बन जाता है।
टाइप-अवेयर एस्लिंट नियमों का उपयोग करके, हमारे कोडबेस में कीवर्ड का any
भी प्रकटन गलती या चूक के बजाय एक जानबूझकर किया गया निर्णय होगा। यह दृष्टिकोण हमें अपने स्वयं के कोड के साथ-साथ मानक लाइब्रेरी और तृतीय-पक्ष निर्भरता में any
उपयोग करने से बचाता है।
कुल मिलाकर, एक टाइप-अवेयर लिंटर हमें जावा, गो, रस्ट और अन्य जैसी सांख्यिकीय रूप से टाइप की गई प्रोग्रामिंग भाषाओं के समान प्रकार की सुरक्षा के स्तर को प्राप्त करने की अनुमति देता है। यह बड़ी परियोजनाओं के विकास और रखरखाव को बहुत सरल बनाता है।
मुझे आशा है कि आपने इस लेख से कुछ नया सीखा होगा। पढ़ने के लिए आपका शुक्रिया!