TypeScript
इंटरफेस
खोज…
परिचय
एक इंटरफेस फ़ील्ड और फ़ंक्शंस की एक सूची निर्दिष्ट करता है जो इंटरफ़ेस को लागू करने वाले किसी भी वर्ग पर अपेक्षित हो सकता है। इसके विपरीत, कोई वर्ग तब तक इंटरफ़ेस लागू नहीं कर सकता जब तक कि इंटरफ़ेस पर निर्दिष्ट प्रत्येक फ़ील्ड और फ़ंक्शन न हो।
इंटरफेस का उपयोग करने का प्राथमिक लाभ यह है कि यह एक पॉलीमॉर्फिक तरीके से विभिन्न प्रकार की वस्तुओं का उपयोग करने की अनुमति देता है। इसका कारण यह है कि इंटरफ़ेस को लागू करने वाले किसी भी वर्ग के पास कम से कम उन फ़ील्ड और फ़ंक्शन हैं।
वाक्य - विन्यास
- इंटरफ़ेस इंटरफ़ेस नाम {
- पैरामीटरनाम: पैरामीटरटाइप;
- वैकल्पिकप्रेमनाम ;: पैरामीटरटाइप;
- }
टिप्पणियों
टाइप बनाम उपनाम
किसी वस्तु के आकार को निर्दिष्ट करने के लिए इंटरफेस अच्छे हैं, उदाहरण के लिए किसी व्यक्ति की वस्तु जो आप निर्दिष्ट कर सकते हैं
interface person {
id?: number;
name: string;
age: number;
}
हालाँकि, यदि आप किसी व्यक्ति का SQL डेटाबेस में संग्रहित करना चाहते हैं, तो आप क्या कहना चाहते हैं? प्रत्येक DB प्रविष्टि के रूप में देखने पर आकृति की एक पंक्ति होती है [string, string, number]
(ताकि स्ट्रिंग्स या संख्याओं की एक सरणी), ऐसा कोई तरीका नहीं है जिससे आप इसे ऑब्जेक्ट आकृति के रूप में प्रस्तुत कर सकें, क्योंकि पंक्ति में कोई गुण नहीं हैं जैसे, यह सिर्फ एक सरणी है।
यह एक ऐसा अवसर है जहाँ उपयोगी प्रकार आते हैं। प्रत्येक फ़ंक्शन को निर्दिष्ट करने के बजाय जो पंक्ति पैरामीटर function processRow(row: [string, string, number])
स्वीकार करता है function processRow(row: [string, string, number])
, आप पंक्ति के लिए एक अलग प्रकार का उपनाम बना सकते हैं और फिर प्रत्येक फ़ंक्शन में उसका उपयोग कर सकते हैं:
type Row = [string, string, number];
function processRow(row: Row)
आधिकारिक इंटरफ़ेस प्रलेखन
https://www.typescriptlang.org/docs/handbook/interfaces.html
मौजूदा इंटरफ़ेस में फ़ंक्शंस या गुण जोड़ें
मान लें कि हमारे पास JQuery
प्रकार की परिभाषा का संदर्भ है और हम इसे एक प्लगइन से अतिरिक्त कार्यों के लिए विस्तारित करना चाहते हैं, जिसमें हम शामिल थे और जिसकी आधिकारिक प्रकार की परिभाषा नहीं है। हम एक ही JQuery
नाम के साथ एक अलग इंटरफ़ेस घोषणा में प्लगइन द्वारा जोड़े गए कार्यों की घोषणा करके इसे आसानी से बढ़ा सकते हैं:
interface JQuery {
pluginFunctionThatDoesNothing(): void;
// create chainable function
manipulateDOM(HTMLElement): JQuery;
}
कंपाइलर सभी घोषणाओं को एक ही नाम से एक में मिलाएगा - अधिक विवरण के लिए घोषणा विलय देखें।
क्लास इंटरफ़ेस
अन्य प्रकार के कोड इसके साथ कैसे सहभागिता कर सकते हैं, इसे परिभाषित करने के लिए इंटरफ़ेस में public
चर और तरीके टाइप करें।
interface ISampleClassInterface {
sampleVariable: string;
sampleMethod(): void;
optionalVariable?: string;
}
यहां हम एक वर्ग बनाते हैं जो इंटरफ़ेस को लागू करता है।
class SampleClass implements ISampleClassInterface {
public sampleVariable: string;
private answerToLifeTheUniverseAndEverything: number;
constructor() {
this.sampleVariable = 'string value';
this.answerToLifeTheUniverseAndEverything = 42;
}
public sampleMethod(): void {
// do nothing
}
private answer(q: any): number {
return this.answerToLifeTheUniverseAndEverything;
}
}
उदाहरण दिखाता है कि एक इंटरफ़ेस ISampleClassInterface
और इंटरफ़ेस को implements
वाला क्लास SampleClass
ISampleClassInterface
कैसे बनाया implements
।
विस्तृत इंटरफ़ेस
मान लीजिए कि हमारे पास एक इंटरफ़ेस है:
interface IPerson {
name: string;
age: number;
breath(): void;
}
और हम व्यक्ति का एक ही गुण है, जो अधिक विशिष्ट इंटरफ़ेस बनाना चाहते हैं, तो हम उसका उपयोग कर सकते हैं extends
कीवर्ड:
interface IManager extends IPerson {
managerId: number;
managePeople(people: IPerson[]): void;
}
इसके अलावा कई इंटरफेस का विस्तार करना संभव है।
प्रकार लागू करने के लिए इंटरफेस का उपयोग करना
टाइपस्क्रिप्ट के मुख्य लाभों में से एक यह है कि यह डेटा प्रकार के मूल्यों को लागू करता है जो आप गलतियों को रोकने में मदद करने के लिए अपने कोड के आसपास से गुजर रहे हैं।
मान लीजिए कि आप एक पालतू डेटिंग एप्लिकेशन बना रहे हैं।
आपके पास यह सरल कार्य है जो यह जांचता है कि क्या दो पालतू जानवर एक-दूसरे के साथ संगत हैं ...
checkCompatible(petOne, petTwo) {
if (petOne.species === petTwo.species &&
Math.abs(petOne.age - petTwo.age) <= 5) {
return true;
}
}
यह पूरी तरह कार्यात्मक कोड है, लेकिन यह किसी के लिए बहुत आसान होगा, विशेष रूप से इस एप्लिकेशन पर काम करने वाले अन्य लोग जो इस फ़ंक्शन को नहीं लिखते हैं, इस बात से अनजान हैं कि वे इसे 'प्रजातियों' और 'उम्र' के साथ वस्तुओं को पारित करने वाले हैं। गुण। वे गलती से checkCompatible(petOne.species, petTwo.species)
कोशिश कर सकते हैं और फिर फ़ंक्शन द्वारा petOne.species.species या petOne.species.age तक पहुँचने का प्रयास करने पर फेंकी गई त्रुटियों का पता लगाने के लिए छोड़ दिया जा सकता है!
पालतू जानवरों के मापदंडों पर हमारे द्वारा वांछित गुणों को निर्दिष्ट करने से एक तरीका यह हो सकता है:
checkCompatible(petOne: {species: string, age: number}, petTwo: {species: string, age: number}) {
//...
}
इस मामले में, टाइपस्क्रिप्ट यह सुनिश्चित करेगी कि फ़ंक्शन में दी गई हर चीज में 'प्रजातियां' और 'आयु' गुण हैं (यह ठीक है यदि उनके पास अतिरिक्त गुण हैं), लेकिन यह केवल एक दोतरफा समाधान का एक सा है, यहां तक कि केवल दो गुणों के साथ निर्दिष्ट किया गया है। इंटरफेस के साथ, एक बेहतर तरीका है!
पहले हम अपने इंटरफ़ेस को परिभाषित करते हैं:
interface Pet {
species: string;
age: number;
//We can add more properties if we choose.
}
अब हमें बस इतना करना है कि हमारे नए इंटरफेस के रूप में हमारे मापदंडों का प्रकार निर्दिष्ट करें, जैसे ...
checkCompatible(petOne: Pet, petTwo: Pet) {
//...
}
... और टाइपस्क्रिप्ट सुनिश्चित करेगा कि हमारे फ़ंक्शन में दिए गए पैरामीटर में पालतू इंटरफ़ेस में निर्दिष्ट गुण हैं!
जेनेरिक इंटरफेस
कक्षाओं की तरह, इंटरफेस भी पॉलीमॉर्फिक पैरामीटर (उर्फ जेनरिक) प्राप्त कर सकते हैं।
इंटरफेसेस पर जेनेरिक पैरामीटर की घोषणा
interface IStatus<U> {
code: U;
}
interface IEvents<T> {
list: T[];
emit(event: T): void;
getAll(): T[];
}
यहां, आप देख सकते हैं कि हमारे दो इंटरफेस कुछ सामान्य पैरामीटर, टी और यू लेते हैं।
जेनेरिक इंटरफेस को लागू करना
हम इंटरफ़ेस IEvents को लागू करने के लिए एक साधारण वर्ग बनाएंगे ।
class State<T> implements IEvents<T> {
list: T[];
constructor() {
this.list = [];
}
emit(event: T): void {
this.list.push(event);
}
getAll(): T[] {
return this.list;
}
}
आइए हमारे राज्य वर्ग के कुछ उदाहरण बनाएं।
हमारे उदाहरण में, State
क्लास IStatus<T>
का उपयोग करके एक सामान्य स्थिति को संभाल IStatus<T>
। इस तरह, इंटरफ़ेस IEvent<T>
एक IStatus<T>
भी संभाल IStatus<T>
।
const s = new State<IStatus<number>>();
// The 'code' property is expected to be a number, so:
s.emit({ code: 200 }); // works
s.emit({ code: '500' }); // type error
s.getAll().forEach(event => console.log(event.code));
यहां हमारा State
क्लास ISatus<number>
टाइप किया गया है।
const s2 = new State<IStatus<Code>>();
//We are able to emit code as the type Code
s2.emit({ code: { message: 'OK', status: 200 } });
s2.getAll().map(event => event.code).forEach(event => {
console.log(event.message);
console.log(event.status);
});
हमारा State
वर्ग IStatus<Code>
रूप में टाइप किया गया है। इस तरह, हम अपनी उत्सर्जन विधि के लिए अधिक जटिल प्रकार पारित करने में सक्षम हैं।
जैसा कि आप देख सकते हैं, जेनेरिक इंटरफेस सांख्यिकीय रूप से टाइप किए गए कोड के लिए बहुत उपयोगी उपकरण हो सकते हैं।
बहुरूपता के लिए इंटरफेस का उपयोग करना
बहुरूपता को प्राप्त करने के लिए इंटरफेस का उपयोग करने के लिए प्राथमिक कारण और भविष्य में इंटरफ़ेस के तरीकों को लागू करने के लिए डेवलपर्स को अपने तरीके से लागू करने के लिए प्रदान करना है।
मान लीजिए कि हमारे पास एक इंटरफ़ेस और तीन वर्ग हैं:
interface Connector{
doConnect(): boolean;
}
यह कनेक्टर इंटरफ़ेस है। अब हम इसे Wifi संचार के लिए लागू करेंगे।
export class WifiConnector implements Connector{
public doConnect(): boolean{
console.log("Connecting via wifi");
console.log("Get password");
console.log("Lease an IP for 24 hours");
console.log("Connected");
return true
}
}
यहाँ हमने अपना ठोस वर्ग WifiConnector
नाम से विकसित किया है जिसका अपना कार्यान्वयन है। यह अब प्रकार Connector
।
अब हम अपना System
बना रहे हैं जिसमें एक घटक Connector
। इसे निर्भरता इंजेक्शन कहा जाता है।
export class System {
constructor(private connector: Connector){ #inject Connector type
connector.doConnect()
}
}
constructor(private connector: Connector)
यह लाइन यहां बहुत महत्वपूर्ण है। Connector
एक इंटरफ़ेस है और इसमें doConnect()
होना चाहिए। जैसा कि Connector
एक इंटरफ़ेस है इस वर्ग System
में बहुत अधिक लचीलापन है। हम किसी भी प्रकार को पारित कर सकते हैं जिसने Connector
इंटरफ़ेस लागू किया है। भविष्य के डेवलपर में अधिक लचीलापन प्राप्त होता है। उदाहरण के लिए, अब डेवलपर ब्लूटूथ कनेक्शन मॉड्यूल जोड़ना चाहते हैं:
export class BluetoothConnector implements Connector{
public doConnect(): boolean{
console.log("Connecting via Bluetooth");
console.log("Pair with PIN");
console.log("Connected");
return true
}
}
देखें कि वाईफ़ाई और ब्लूटूथ का अपना कार्यान्वयन है। कनेक्ट करने का अपना अलग तरीका है। हालाँकि, इसलिए दोनों ने ही टाइप Connector
लागू किया है अब टाइप Connector
। ताकि हम उनमें से किसी को System
क्लास में कंस्ट्रक्टर पैरामीटर के रूप में पास कर सकें। इसे बहुरूपता कहा जाता है। क्लास System
अब इस बात से अवगत नहीं है कि क्या यह ब्लूटूथ / Wifi है, यहाँ तक कि हम एक अन्य कम्युनिकेशन मॉड्यूल जैसे Inferade, ब्लूटूथ 5 और जो भी कनेक्ट Connector
इंटरफ़ेस को लागू करके जोड़ सकते हैं।
इसे डक टाइपिंग कहा जाता है। Connector
प्रकार अब गतिशील है क्योंकि doConnect()
सिर्फ एक प्लेसहोल्डर है और डेवलपर इसे अपने स्वयं के रूप में लागू करता है।
अगर constructor(private connector: WifiConnector)
जहां WifiConnector
एक ठोस वर्ग है तो क्या होगा? तब System
वर्ग केवल WifiConnector के साथ कुछ और ही कसकर जोड़ेगा। यहाँ इंटरफ़ेस ने बहुरूपता द्वारा हमारी समस्या को हल किया।
इंप्लिमेंट इम्प्लीमेंटेशन एंड ऑब्जेक्ट शेप
टाइपस्क्रिप्ट इंटरफेस का समर्थन करता है, लेकिन कंपाइलर जावास्क्रिप्ट का उत्पादन करता है, जो नहीं करता है। इसलिए, संकलन चरण में इंटरफ़ेस प्रभावी रूप से खो जाते हैं। यही कारण है कि इंटरफेस पर टाइपिंग चेकिंग ऑब्जेक्ट के आकार पर निर्भर करती है - मतलब यह है कि ऑब्जेक्ट इंटरफ़ेस पर फ़ील्ड्स और फ़ंक्शंस को सपोर्ट करता है या नहीं - इस बात पर कि इंटरफ़ेस वास्तव में लागू किया गया है या नहीं।
interface IKickable {
kick(distance: number): void;
}
class Ball {
kick(distance: number): void {
console.log("Kicked", distance, "meters!");
}
}
let kickable: IKickable = new Ball();
kickable.kick(40);
यहां तक कि अगर Ball
स्पष्ट रूप से IKickable
लागू नहीं करता है, तो एक Ball
उदाहरण को निर्दिष्ट किए जाने पर भी IKickable
को (और के रूप में हेरफेर) सौंपा जा सकता है।