ಹೆಚ್ಚು ಹೊಂದಿಕೊಳ್ಳುವ, ಸುರಕ್ಷಿತ ಮತ್ತು ನಿರ್ವಹಿಸಬಲ್ಲ ಕೋಡ್ ರಚಿಸಲು ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ವೇರಿಯನ್ಸ್ ಅನೋಟೇಶನ್ಗಳು ಮತ್ತು ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳ ಶಕ್ತಿಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿ. ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳೊಂದಿಗೆ ಆಳವಾದ ನೋಟ.
ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ ವೇರಿಯನ್ಸ್ ಅನೋಟೇಶನ್ಗಳು: ದೃಢವಾದ ಕೋಡ್ಗಾಗಿ ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ಮಾಸ್ಟರಿಂಗ್ ಮಾಡುವುದು
ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್, ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನ ಒಂದು ಸೂಪರ್ಸೆಟ್, ಸ್ಟ್ಯಾಟಿಕ್ ಟೈಪಿಂಗ್ ಅನ್ನು ಒದಗಿಸುತ್ತದೆ, ಇದು ಕೋಡ್ನ ವಿಶ್ವಾಸಾರ್ಹತೆ ಮತ್ತು ನಿರ್ವಹಣೆಯನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ. ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ಹೆಚ್ಚು ಸುಧಾರಿತ, ಆದರೂ ಶಕ್ತಿಯುತ, ವೈಶಿಷ್ಟ್ಯವೆಂದರೆ ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳ ಜೊತೆಗೆ ವೇರಿಯನ್ಸ್ ಅನೋಟೇಶನ್ಗಳಿಗೆ ಅದರ ಬೆಂಬಲ. ನಿಜವಾಗಿಯೂ ದೃಢವಾದ ಮತ್ತು ಹೊಂದಿಕೊಳ್ಳುವ ಜೆನೆರಿಕ್ ಕೋಡ್ ಬರೆಯಲು ಈ ಪರಿಕಲ್ಪನೆಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಬಹಳ ಮುಖ್ಯ. ಈ ಬ್ಲಾಗ್ ಪೋಸ್ಟ್ ವೇರಿಯನ್ಸ್, ಕೋವೇರಿಯನ್ಸ್, ಕಾಂಟ್ರಾವೇರಿಯನ್ಸ್ ಮತ್ತು ಇನ್ವೇರಿಯನ್ಸ್ಗಳ ಬಗ್ಗೆ ಆಳವಾಗಿ ವಿವರಿಸುತ್ತದೆ, ಜೊತೆಗೆ ಸುರಕ್ಷಿತ ಮತ್ತು ಹೆಚ್ಚು ಮರುಬಳಕೆ ಮಾಡಬಹುದಾದ ಕಾಂಪೊನೆಂಟ್ಗಳನ್ನು ನಿರ್ಮಿಸಲು ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ಪರಿಣಾಮಕಾರಿಯಾಗಿ ಬಳಸುವುದು ಹೇಗೆ ಎಂದು ವಿವರಿಸುತ್ತದೆ.
ವೇರಿಯನ್ಸ್ ಅನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು
ವೇರಿಯನ್ಸ್ ಎಂಬುದು ಟೈಪ್ಗಳ ನಡುವಿನ ಸಬ್ಟೈಪ್ ಸಂಬಂಧವು ನಿರ್ಮಿತ ಟೈಪ್ಗಳ (ಉದಾಹರಣೆಗೆ, ಜೆನೆರಿಕ್ ಟೈಪ್ಗಳು) ನಡುವಿನ ಸಬ್ಟೈಪ್ ಸಂಬಂಧದ ಮೇಲೆ ಹೇಗೆ ಪರಿಣಾಮ ಬೀರುತ್ತದೆ ಎಂಬುದನ್ನು ವಿವರಿಸುತ್ತದೆ. ಪ್ರಮುಖ ಪದಗಳನ್ನು ವಿಂಗಡಿಸೋಣ:
- ಕೋವೇರಿಯನ್ಸ್: ಒಂದು ಜೆನೆರಿಕ್ ಟೈಪ್
Container<T>
ಕೋವೇರಿಯಂಟ್ ಆಗಿರುತ್ತದೆ, ಯಾವಾಗSubtype
ಎಂಬುದುSupertype
ನ ಸಬ್ಟೈಪ್ ಆಗಿದ್ದರೆ,Container<Subtype>
ಕೂಡContainer<Supertype>
ನ ಸಬ್ಟೈಪ್ ಆಗಿರುತ್ತದೆ. ಇದನ್ನು ಸಬ್ಟೈಪ್ ಸಂಬಂಧವನ್ನು ಸಂರಕ್ಷಿಸುವುದು ಎಂದು ಯೋಚಿಸಿ. ಅನೇಕ ಭಾಷೆಗಳಲ್ಲಿ (ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ಗಳಲ್ಲಿ ನೇರವಾಗಿ ಅಲ್ಲ), ಜೆನೆರಿಕ್ ಅರೇಗಳು ಕೋವೇರಿಯಂಟ್ ಆಗಿರುತ್ತವೆ. ಉದಾಹರಣೆಗೆ,Cat
ಎಂಬುದುAnimal
ಅನ್ನು ವಿಸ್ತರಿಸಿದರೆ, `Array<Cat>` ಎಂಬುದು `Array<Animal>`ನ ಸಬ್ಟೈಪ್ನಂತೆ *ವರ್ತಿಸುತ್ತದೆ* (ಆದರೂ ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ಟೈಪ್ ಸಿಸ್ಟಮ್ ರನ್ಟೈಮ್ ದೋಷಗಳನ್ನು ತಡೆಯಲು ಸ್ಪಷ್ಟವಾದ ಕೋವೇರಿಯನ್ಸ್ ಅನ್ನು ತಪ್ಪಿಸುತ್ತದೆ). - ಕಾಂಟ್ರಾವೇರಿಯನ್ಸ್: ಒಂದು ಜೆನೆರಿಕ್ ಟೈಪ್
Container<T>
ಕಾಂಟ್ರಾವೇರಿಯಂಟ್ ಆಗಿರುತ್ತದೆ, ಯಾವಾಗSubtype
ಎಂಬುದುSupertype
ನ ಸಬ್ಟೈಪ್ ಆಗಿದ್ದರೆ,Container<Supertype>
ಕೂಡContainer<Subtype>
ನ ಸಬ್ಟೈಪ್ ಆಗಿರುತ್ತದೆ. ಇದು ಸಬ್ಟೈಪ್ ಸಂಬಂಧವನ್ನು ಹಿಮ್ಮುಖಗೊಳಿಸುತ್ತದೆ. ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ ಟೈಪ್ಗಳು ಕಾಂಟ್ರಾವೇರಿಯನ್ಸ್ ಅನ್ನು ಪ್ರದರ್ಶಿಸುತ್ತವೆ. - ಇನ್ವೇರಿಯನ್ಸ್: ಒಂದು ಜೆನೆರಿಕ್ ಟೈಪ್
Container<T>
ಇನ್ವೇರಿಯಂಟ್ ಆಗಿರುತ್ತದೆ, ಯಾವಾಗSubtype
ಎಂಬುದುSupertype
ನ ಸಬ್ಟೈಪ್ ಆಗಿದ್ದರೂ,Container<Subtype>
ಎಂಬುದುContainer<Supertype>
ನ ಸಬ್ಟೈಪ್ ಅಥವಾ ಸೂಪರ್ಟೈಪ್ ಆಗಿರುವುದಿಲ್ಲ. ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ಜೆನೆರಿಕ್ ಟೈಪ್ಗಳು ಸಾಮಾನ್ಯವಾಗಿ ಇನ್ವೇರಿಯಂಟ್ ಆಗಿರುತ್ತವೆ (ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ ನಿಯಮಗಳ ಮೂಲಕ ಕಾಂಟ್ರಾವೇರಿಯನ್ಸ್ಗಾಗಿ ಪರೋಕ್ಷವಾಗಿ ಹೊರತುಪಡಿಸಿ).
ಇದನ್ನು ಒಂದು ಸಾದೃಶ್ಯದೊಂದಿಗೆ ನೆನಪಿಟ್ಟುಕೊಳ್ಳುವುದು ಸುಲಭ: ನಾಯಿ ಕಾಲರ್ಗಳನ್ನು ತಯಾರಿಸುವ ಕಾರ್ಖಾನೆಯನ್ನು ಪರಿಗಣಿಸಿ. ಕೋವೇರಿಯಂಟ್ ಕಾರ್ಖಾನೆಯು ನಾಯಿಗಳಿಗೆ ಕಾಲರ್ಗಳನ್ನು ಉತ್ಪಾದಿಸಬಹುದಾದರೆ, ಅದು ಎಲ್ಲಾ ರೀತಿಯ ಪ್ರಾಣಿಗಳಿಗೆ ಕಾಲರ್ಗಳನ್ನು ಉತ್ಪಾದಿಸಬಹುದು, ಇದು ಸಬ್ಟೈಪಿಂಗ್ ಸಂಬಂಧವನ್ನು ಸಂರಕ್ಷಿಸುತ್ತದೆ. ಕಾಂಟ್ರಾವೇರಿಯಂಟ್ ಕಾರ್ಖಾನೆಯು ನಾಯಿ ಕಾಲರ್ಗಳನ್ನು *ಬಳಸಿಕೊಳ್ಳಲು* ಸಾಧ್ಯವಾದರೆ, ಅದು ಯಾವುದೇ ರೀತಿಯ ಪ್ರಾಣಿ ಕಾಲರ್ ಅನ್ನು ಬಳಸಿಕೊಳ್ಳಬಹುದು. ಕಾರ್ಖಾನೆಯು ಕೇವಲ ನಾಯಿ ಕಾಲರ್ಗಳೊಂದಿಗೆ ಮಾತ್ರ ಕೆಲಸ ಮಾಡಬಹುದಾದರೆ ಮತ್ತು ಬೇರೇನೂ ಇಲ್ಲದಿದ್ದರೆ, ಅದು ಪ್ರಾಣಿ ಪ್ರಕಾರಕ್ಕೆ ಇನ್ವೇರಿಯಂಟ್ ಆಗಿದೆ.
ವೇರಿಯನ್ಸ್ ಏಕೆ ಮುಖ್ಯ?
ವಿಶೇಷವಾಗಿ ಜೆನೆರಿಕ್ಸ್ಗಳೊಂದಿಗೆ ಕೆಲಸ ಮಾಡುವಾಗ, ಟೈಪ್-ಸುರಕ್ಷಿತ ಕೋಡ್ ಬರೆಯಲು ವೇರಿಯನ್ಸ್ ಅನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಬಹಳ ಮುಖ್ಯ. ಕೋವೇರಿಯನ್ಸ್ ಅಥವಾ ಕಾಂಟ್ರಾವೇರಿಯನ್ಸ್ ಅನ್ನು ತಪ್ಪಾಗಿ ಊಹಿಸುವುದು ರನ್ಟೈಮ್ ದೋಷಗಳಿಗೆ ಕಾರಣವಾಗಬಹುದು, ಇದನ್ನು ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ಟೈಪ್ ಸಿಸ್ಟಮ್ ತಡೆಯಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ. ಈ ದೋಷಪೂರಿತ ಉದಾಹರಣೆಯನ್ನು ಪರಿಗಣಿಸಿ (ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನಲ್ಲಿ, ಆದರೆ ಪರಿಕಲ್ಪನೆಯನ್ನು ವಿವರಿಸಲು):
// ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಉದಾಹರಣೆ (ದೃಷ್ಟಾಂತಕ್ಕಾಗಿ ಮಾತ್ರ, ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ ಅಲ್ಲ)
function modifyAnimals(animals, modifier) {
for (let i = 0; i < animals.length; i++) {
animals[i] = modifier(animals[i]);
}
}
function sound(animal) { return animal.sound(); }
function Cat(name) { this.name = name; this.sound = () => "Meow!"; }
Cat.prototype = Object.create({ sound: () => "Generic Animal Sound"});
function Animal(name) { this.name = name; this.sound = () => "Generic Animal Sound"; }
let cats = [new Cat("Whiskers"), new Cat("Mittens")];
//ಈ ಕೋಡ್ ದೋಷವನ್ನು ನೀಡುತ್ತದೆ ಏಕೆಂದರೆ Animal ಅನ್ನು Cat ಅರೇಗೆ ನಿಯೋಜಿಸುವುದು ಸರಿಯಲ್ಲ
//modifyAnimals(cats, (animal) => new Animal("Generic"));
//ಇದು ಕೆಲಸ ಮಾಡುತ್ತದೆ ಏಕೆಂದರೆ Cat ಅನ್ನು Cat ಅರೇಗೆ ನಿಯೋಜಿಸಲಾಗಿದೆ
modifyAnimals(cats, (cat) => new Cat("Fuzzy"));
//cats.forEach(cat => console.log(cat.sound()));
ಈ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಉದಾಹರಣೆಯು ಸಂಭಾವ್ಯ ಸಮಸ್ಯೆಯನ್ನು ನೇರವಾಗಿ ತೋರಿಸುತ್ತದೆಯಾದರೂ, ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ಟೈಪ್ ಸಿಸ್ಟಮ್ ಸಾಮಾನ್ಯವಾಗಿ ಈ ರೀತಿಯ ನೇರ ನಿಯೋಜನೆಯನ್ನು *ತಡೆಯುತ್ತದೆ*. ಹೆಚ್ಚು ಸಂಕೀರ್ಣ ಸನ್ನಿವೇಶಗಳಲ್ಲಿ, ವಿಶೇಷವಾಗಿ ಫಂಕ್ಷನ್ ಟೈಪ್ಗಳು ಮತ್ತು ಜೆನೆರಿಕ್ ಇಂಟರ್ಫೇಸ್ಗಳೊಂದಿಗೆ ಕೆಲಸ ಮಾಡುವಾಗ, ವೇರಿಯನ್ಸ್ ಪರಿಗಣನೆಗಳು ಮುಖ್ಯವಾಗುತ್ತವೆ.
ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳು
ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳು ಜೆನೆರಿಕ್ ಟೈಪ್ಗಳು ಮತ್ತು ಫಂಕ್ಷನ್ಗಳಲ್ಲಿ ಟೈಪ್ ಆರ್ಗ್ಯುಮೆಂಟ್ಗಳಾಗಿ ಬಳಸಬಹುದಾದ ಟೈಪ್ಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತವೆ. ಅವು ಟೈಪ್ಗಳ ನಡುವಿನ ಸಂಬಂಧಗಳನ್ನು ವ್ಯಕ್ತಪಡಿಸಲು ಮತ್ತು ಕೆಲವು ಗುಣಲಕ್ಷಣಗಳನ್ನು ಜಾರಿಗೊಳಿಸಲು ಒಂದು ಮಾರ್ಗವನ್ನು ಒದಗಿಸುತ್ತವೆ. ಇದು ಟೈಪ್ ಸುರಕ್ಷತೆಯನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ಮತ್ತು ಹೆಚ್ಚು ನಿಖರವಾದ ಟೈಪ್ ಇನ್ಫರೆನ್ಸ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಒಂದು ಶಕ್ತಿಯುತ ಯಾಂತ್ರಿಕತೆಯಾಗಿದೆ.
extends
ಕೀವರ್ಡ್
ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಲು ಪ್ರಾಥಮಿಕ ಮಾರ್ಗವೆಂದರೆ extends
ಕೀವರ್ಡ್ ಬಳಸುವುದು. ಈ ಕೀವರ್ಡ್ ಒಂದು ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ನಿರ್ದಿಷ್ಟ ಟೈಪ್ನ ಸಬ್ಟೈಪ್ ಆಗಿರಬೇಕು ಎಂದು ನಿರ್ದಿಷ್ಟಪಡಿಸುತ್ತದೆ.
function logName<T extends { name: string }>(obj: T): void {
console.log(obj.name);
}
// ಮಾನ್ಯ ಬಳಕೆ
logName({ name: "Alice", age: 30 });
// ದೋಷ: '{}' ಪ್ರಕಾರದ ಆರ್ಗ್ಯುಮೆಂಟ್ '{ name: string; }' ಪ್ರಕಾರದ ಪ್ಯಾರಾಮೀಟರ್ಗೆ ನಿಯೋಜಿಸಲಾಗುವುದಿಲ್ಲ.
// logName({});
ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ T
ಎಂಬುದು string
ಪ್ರಕಾರದ name
ಪ್ರಾಪರ್ಟಿ ಹೊಂದಿರುವ ಟೈಪ್ಗೆ ನಿರ್ಬಂಧಿತವಾಗಿದೆ. ಇದು logName
ಫಂಕ್ಷನ್ ತನ್ನ ಆರ್ಗ್ಯುಮೆಂಟ್ನ name
ಪ್ರಾಪರ್ಟಿಯನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಪ್ರವೇಶಿಸಬಹುದು ಎಂದು ಖಚಿತಪಡಿಸುತ್ತದೆ.
ಇಂಟರ್ಸೆಕ್ಷನ್ ಟೈಪ್ಗಳೊಂದಿಗೆ ಬಹು ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳು
ನೀವು ಇಂಟರ್ಸೆಕ್ಷನ್ ಟೈಪ್ಗಳನ್ನು (&
) ಬಳಸಿ ಬಹು ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ಸಂಯೋಜಿಸಬಹುದು. ಇದು ಒಂದು ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಬಹು ಷರತ್ತುಗಳನ್ನು ಪೂರೈಸಬೇಕು ಎಂದು ನಿರ್ದಿಷ್ಟಪಡಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ.
interface Named {
name: string;
}
interface Aged {
age: number;
}
function logPerson<T extends Named & Aged>(person: T): void {
console.log(`Name: ${person.name}, Age: ${person.age}`);
}
// ಮಾನ್ಯ ಬಳಕೆ
logPerson({ name: "Bob", age: 40 });
// ದೋಷ: '{ name: string; }' ಪ್ರಕಾರದ ಆರ್ಗ್ಯುಮೆಂಟ್ 'Named & Aged' ಪ್ರಕಾರದ ಪ್ಯಾರಾಮೀಟರ್ಗೆ ನಿಯೋಜಿಸಲಾಗುವುದಿಲ್ಲ.
// '{ name: string; }' ಪ್ರಕಾರದಲ್ಲಿ 'age' ಪ್ರಾಪರ್ಟಿ ಕಾಣೆಯಾಗಿದೆ ಆದರೆ 'Aged' ಪ್ರಕಾರದಲ್ಲಿ ಅಗತ್ಯವಿದೆ.
// logPerson({ name: "Charlie" });
ಇಲ್ಲಿ, ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ T
ಎಂಬುದು Named
ಮತ್ತು Aged
ಎರಡೂ ಆಗಿರುವ ಟೈಪ್ಗೆ ನಿರ್ಬಂಧಿತವಾಗಿದೆ. ಇದು logPerson
ಫಂಕ್ಷನ್ name
ಮತ್ತು age
ಎರಡೂ ಪ್ರಾಪರ್ಟಿಗಳನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಪ್ರವೇಶಿಸಬಹುದು ಎಂದು ಖಚಿತಪಡಿಸುತ್ತದೆ.
ಜೆನೆರಿಕ್ ಕ್ಲಾಸ್ಗಳೊಂದಿಗೆ ಟೈಪ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ಬಳಸುವುದು
ಜೆನೆರಿಕ್ ಕ್ಲಾಸ್ಗಳೊಂದಿಗೆ ಕೆಲಸ ಮಾಡುವಾಗ ಟೈಪ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳು ಅಷ್ಟೇ ಉಪಯುಕ್ತವಾಗಿವೆ.
interface Printable {
print(): void;
}
class Document<T extends Printable> {
content: T;
constructor(content: T) {
this.content = content;
}
printDocument(): void {
this.content.print();
}
}
class Invoice implements Printable {
invoiceNumber: string;
constructor(invoiceNumber: string) {
this.invoiceNumber = invoiceNumber;
}
print(): void {
console.log(`Printing invoice: ${this.invoiceNumber}`);
}
}
const myInvoice = new Invoice("INV-2023-123");
const document = new Document(myInvoice);
document.printDocument(); // ಔಟ್ಪುಟ್: Printing invoice: INV-2023-123
ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, Document
ಕ್ಲಾಸ್ ಜೆನೆರಿಕ್ ಆಗಿದೆ, ಆದರೆ ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ T
ಎಂಬುದು Printable
ಇಂಟರ್ಫೇಸ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವ ಟೈಪ್ಗೆ ನಿರ್ಬಂಧಿತವಾಗಿದೆ. ಇದು Document
ನ content
ಆಗಿ ಬಳಸಲಾಗುವ ಯಾವುದೇ ಆಬ್ಜೆಕ್ಟ್ print
ಮೆಥಡ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ ಎಂದು ಖಾತರಿಪಡಿಸುತ್ತದೆ. ಇದು ಅಂತರರಾಷ್ಟ್ರೀಯ ಸಂದರ್ಭಗಳಲ್ಲಿ ವಿಶೇಷವಾಗಿ ಉಪಯುಕ್ತವಾಗಿದೆ, ಅಲ್ಲಿ ಪ್ರಿಂಟಿಂಗ್ ವಿವಿಧ ಸ್ವರೂಪಗಳು ಅಥವಾ ಭಾಷೆಗಳನ್ನು ಒಳಗೊಂಡಿರಬಹುದು, ಅದಕ್ಕೆ ಸಾಮಾನ್ಯ print
ಇಂಟರ್ಫೇಸ್ ಅಗತ್ಯವಿರುತ್ತದೆ.
ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನಲ್ಲಿ ಕೋವೇರಿಯನ್ಸ್, ಕಾಂಟ್ರಾವೇರಿಯನ್ಸ್ ಮತ್ತು ಇನ್ವೇರಿಯನ್ಸ್ (ಮರುಪರಿಶೀಲನೆ)
ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನಲ್ಲಿ ಸ್ಪಷ್ಟವಾದ ವೇರಿಯನ್ಸ್ ಅನೋಟೇಶನ್ಗಳು ಇಲ್ಲದಿದ್ದರೂ (ಕೆಲವು ಇತರ ಭಾಷೆಗಳಲ್ಲಿ in
ಮತ್ತು out
ನಂತೆ), ಇದು ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ಗಳನ್ನು ಹೇಗೆ ಬಳಸಲಾಗುತ್ತದೆ ಎಂಬುದರ ಆಧಾರದ ಮೇಲೆ ಪರೋಕ್ಷವಾಗಿ ವೇರಿಯನ್ಸ್ ಅನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ. ಇದು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದರ ಸೂಕ್ಷ್ಮ ವ್ಯತ್ಯಾಸಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಮುಖ್ಯ, ವಿಶೇಷವಾಗಿ ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ಗಳೊಂದಿಗೆ.
ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ ಟೈಪ್ಗಳು: ಕಾಂಟ್ರಾವೇರಿಯನ್ಸ್
ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ ಟೈಪ್ಗಳು ಕಾಂಟ್ರಾವೇರಿಯಂಟ್ ಆಗಿರುತ್ತವೆ. ಇದರರ್ಥ ನೀವು ನಿರೀಕ್ಷೆಗಿಂತ ಹೆಚ್ಚು ಸಾಮಾನ್ಯ ಪ್ರಕಾರವನ್ನು ಸ್ವೀಕರಿಸುವ ಫಂಕ್ಷನ್ ಅನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಪಾಸ್ ಮಾಡಬಹುದು. ಏಕೆಂದರೆ ಒಂದು ಫಂಕ್ಷನ್ Supertype
ಅನ್ನು ನಿಭಾಯಿಸಬಲ್ಲದಾದರೆ, ಅದು ಖಂಡಿತವಾಗಿಯೂ Subtype
ಅನ್ನು ನಿಭಾಯಿಸಬಲ್ಲದು.
interface Animal {
name: string;
}
interface Cat extends Animal {
meow(): void;
}
function feedAnimal(animal: Animal): void {
console.log(`Feeding ${animal.name}`);
}
function feedCat(cat: Cat): void {
console.log(`Feeding ${cat.name} (a cat)`);
cat.meow();
}
// ಇದು ಮಾನ್ಯವಾಗಿದೆ ಏಕೆಂದರೆ ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ ಟೈಪ್ಗಳು ಕಾಂಟ್ರಾವೇರಿಯಂಟ್ ಆಗಿರುತ್ತವೆ
let feed: (animal: Animal) => void = feedCat;
let genericAnimal:Animal = {name: "Generic Animal"};
feed(genericAnimal); // ಕೆಲಸ ಮಾಡುತ್ತದೆ ಆದರೆ ಮಿಯಾಂವ್ ಮಾಡುವುದಿಲ್ಲ
let mittens: Cat = { name: "Mittens", meow: () => {console.log("Mittens meows");}};
feed(mittens); // ಇದು ಕೂಡ ಕೆಲಸ ಮಾಡುತ್ತದೆ, ಮತ್ತು ನಿಜವಾದ ಫಂಕ್ಷನ್ ಅನ್ನು ಅವಲಂಬಿಸಿ ಮಿಯಾಂವ್ *ಮಾಡಬಹುದು*.
ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, feedCat
ಎಂಬುದು (animal: Animal) => void
ನ ಸಬ್ಟೈಪ್ ಆಗಿದೆ. ಏಕೆಂದರೆ feedCat
ಹೆಚ್ಚು ನಿರ್ದಿಷ್ಟವಾದ ಟೈಪ್ (Cat
) ಅನ್ನು ಸ್ವೀಕರಿಸುತ್ತದೆ, ಇದು ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ನಲ್ಲಿನ Animal
ಟೈಪ್ಗೆ ಸಂಬಂಧಿಸಿದಂತೆ ಕಾಂಟ್ರಾವೇರಿಯಂಟ್ ಆಗಿರುತ್ತದೆ. ಇಲ್ಲಿ ಪ್ರಮುಖ ಭಾಗವೆಂದರೆ ನಿಯೋಜನೆ: let feed: (animal: Animal) => void = feedCat;
ಮಾನ್ಯವಾಗಿದೆ.
ರಿಟರ್ನ್ ಟೈಪ್ಗಳು: ಕೋವೇರಿಯನ್ಸ್
ಫಂಕ್ಷನ್ ರಿಟರ್ನ್ ಟೈಪ್ಗಳು ಕೋವೇರಿಯಂಟ್ ಆಗಿರುತ್ತವೆ. ಇದರರ್ಥ ನೀವು ನಿರೀಕ್ಷೆಗಿಂತ ಹೆಚ್ಚು ನಿರ್ದಿಷ್ಟವಾದ ಟೈಪ್ ಅನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಹಿಂತಿರುಗಿಸಬಹುದು. ಒಂದು ಫಂಕ್ಷನ್ Animal
ಅನ್ನು ಹಿಂತಿರುಗಿಸುವ ಭರವಸೆ ನೀಡಿದರೆ, Cat
ಅನ್ನು ಹಿಂತಿರುಗಿಸುವುದು ಸಂಪೂರ್ಣವಾಗಿ ಸ್ವೀಕಾರಾರ್ಹ.
function getAnimal(): Animal {
return { name: "Generic Animal" };
}
function getCat(): Cat {
return { name: "Whiskers", meow: () => { console.log("Whiskers meows"); } };
}
// ಇದು ಮಾನ್ಯವಾಗಿದೆ ಏಕೆಂದರೆ ಫಂಕ್ಷನ್ ರಿಟರ್ನ್ ಟೈಪ್ಗಳು ಕೋವೇರಿಯಂಟ್ ಆಗಿರುತ್ತವೆ
let get: () => Animal = getCat;
let myAnimal: Animal = get();
console.log(myAnimal.name); // ಕೆಲಸ ಮಾಡುತ್ತದೆ
// myAnimal.meow(); // ದೋಷ: 'Animal' ಪ್ರಕಾರದಲ್ಲಿ 'meow' ಪ್ರಾಪರ್ಟಿ ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ.
// Cat-ನಿರ್ದಿಷ್ಟ ಪ್ರಾಪರ್ಟಿಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ನೀವು ಟೈಪ್ ಅಸರ್ಶನ್ ಅನ್ನು ಬಳಸಬೇಕಾಗುತ್ತದೆ
if ((myAnimal as Cat).meow) {
(myAnimal as Cat).meow(); // Whiskers meows
}
ಇಲ್ಲಿ, getCat
ಎಂಬುದು () => Animal
ನ ಸಬ್ಟೈಪ್ ಆಗಿದೆ ಏಕೆಂದರೆ ಅದು ಹೆಚ್ಚು ನಿರ್ದಿಷ್ಟವಾದ ಟೈಪ್ (Cat
) ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ. let get: () => Animal = getCat;
ನಿಯೋಜನೆಯು ಮಾನ್ಯವಾಗಿದೆ.
ಅರೇಗಳು ಮತ್ತು ಜೆನೆರಿಕ್ಸ್: ಇನ್ವೇರಿಯನ್ಸ್ (ಹೆಚ್ಚಾಗಿ)
ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ ಅರೇಗಳು ಮತ್ತು ಹೆಚ್ಚಿನ ಜೆನೆರಿಕ್ ಟೈಪ್ಗಳನ್ನು ಡೀಫಾಲ್ಟ್ ಆಗಿ ಇನ್ವೇರಿಯಂಟ್ ಎಂದು ಪರಿಗಣಿಸುತ್ತದೆ. ಇದರರ್ಥ Cat
ಎಂಬುದು Animal
ಅನ್ನು ವಿಸ್ತರಿಸಿದರೂ, Array<Cat>
ಅನ್ನು Array<Animal>
ನ ಸಬ್ಟೈಪ್ ಎಂದು ಪರಿಗಣಿಸಲಾಗುವುದಿಲ್ಲ. ಇದು ಸಂಭಾವ್ಯ ರನ್ಟೈಮ್ ದೋಷಗಳನ್ನು ತಡೆಯಲು ಉದ್ದೇಶಪೂರ್ವಕ ವಿನ್ಯಾಸದ ಆಯ್ಕೆಯಾಗಿದೆ. ಅನೇಕ ಇತರ ಭಾಷೆಗಳಲ್ಲಿ ಅರೇಗಳು ಕೋವೇರಿಯಂಟ್ನಂತೆ *ವರ್ತಿಸಿದರೂ*, ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ ಸುರಕ್ಷತೆಗಾಗಿ ಅವುಗಳನ್ನು ಇನ್ವೇರಿಯಂಟ್ ಆಗಿ ಮಾಡುತ್ತದೆ.
let animals: Animal[] = [{ name: "Generic Animal" }];
let cats: Cat[] = [{ name: "Whiskers", meow: () => { console.log("Whiskers meows"); } }];
// ದೋಷ: 'Cat[]' ಪ್ರಕಾರವನ್ನು 'Animal[]' ಪ್ರಕಾರಕ್ಕೆ ನಿಯೋಜಿಸಲಾಗುವುದಿಲ್ಲ.
// 'Cat' ಪ್ರಕಾರವನ್ನು 'Animal' ಪ್ರಕಾರಕ್ಕೆ ನಿಯೋಜಿಸಲಾಗುವುದಿಲ್ಲ.
// 'meow' ಪ್ರಾಪರ್ಟಿ 'Animal' ಪ್ರಕಾರದಲ್ಲಿ ಕಾಣೆಯಾಗಿದೆ ಆದರೆ 'Cat' ಪ್ರಕಾರದಲ್ಲಿ ಅಗತ್ಯವಿದೆ.
// animals = cats; // ಇದನ್ನು ಅನುಮತಿಸಿದರೆ ಸಮಸ್ಯೆಗಳನ್ನು ಉಂಟುಮಾಡುತ್ತದೆ!
//ಆದಾಗ್ಯೂ ಇದು ಕೆಲಸ ಮಾಡುತ್ತದೆ
animals[0] = cats[0];
console.log(animals[0].name);
//animals[0].meow(); // ದೋಷ - animals[0] ಅನ್ನು Animal ಪ್ರಕಾರವೆಂದು ನೋಡಲಾಗುತ್ತದೆ, ಆದ್ದರಿಂದ meow ಲಭ್ಯವಿಲ್ಲ
(animals[0] as Cat).meow(); // Cat-ನಿರ್ದಿಷ್ಟ ವಿಧಾನಗಳನ್ನು ಬಳಸಲು ಟೈಪ್ ಅಸರ್ಶನ್ ಅಗತ್ಯವಿದೆ
animals = cats;
ನಿಯೋಜನೆಯನ್ನು ಅನುಮತಿಸುವುದು ಅಸುರಕ್ಷಿತವಾಗಿರುತ್ತದೆ ಏಕೆಂದರೆ ನೀವು ನಂತರ ಜೆನೆರಿಕ್ Animal
ಅನ್ನು animals
ಅರೇಗೆ ಸೇರಿಸಬಹುದು, ಇದು cats
ಅರೇಯ (ಕೇವಲ Cat
ಆಬ್ಜೆಕ್ಟ್ಗಳನ್ನು ಮಾತ್ರ ಹೊಂದಿರಬೇಕಾದ) ಟೈಪ್ ಸುರಕ್ಷತೆಯನ್ನು ಉಲ್ಲಂಘಿಸುತ್ತದೆ. ಈ ಕಾರಣದಿಂದಾಗಿ, ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ ಅರೇಗಳು ಇನ್ವೇರಿಯಂಟ್ ಎಂದು ಊಹಿಸುತ್ತದೆ.
ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆಗಳು ಮತ್ತು ಬಳಕೆಯ ಪ್ರಕರಣಗಳು
ಜೆನೆರಿಕ್ ರೆಪೊಸಿಟರಿ ಪ್ಯಾಟರ್ನ್
ಡೇಟಾ ಪ್ರವೇಶಕ್ಕಾಗಿ ಜೆನೆರಿಕ್ ರೆಪೊಸಿಟರಿ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ಪರಿಗಣಿಸಿ. ನೀವು ಮೂಲ ಎಂಟಿಟಿ ಟೈಪ್ ಮತ್ತು ಆ ಟೈಪ್ನಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುವ ಜೆನೆರಿಕ್ ರೆಪೊಸಿಟರಿ ಇಂಟರ್ಫೇಸ್ ಅನ್ನು ಹೊಂದಿರಬಹುದು.
interface Entity {
id: string;
}
interface Repository<T extends Entity> {
getById(id: string): T | undefined;
save(entity: T): void;
delete(id: string): void;
}
class InMemoryRepository<T extends Entity> implements Repository<T> {
private data: { [id: string]: T } = {};
getById(id: string): T | undefined {
return this.data[id];
}
save(entity: T): void {
this.data[entity.id] = entity;
}
delete(id: string): void {
delete this.data[id];
}
}
interface Product extends Entity {
name: string;
price: number;
}
const productRepository: Repository<Product> = new InMemoryRepository<Product>();
const newProduct: Product = { id: "123", name: "Laptop", price: 1200 };
productRepository.save(newProduct);
const retrievedProduct = productRepository.getById("123");
if (retrievedProduct) {
console.log(`Retrieved product: ${retrievedProduct.name}`);
}
T extends Entity
ಎಂಬ ಟೈಪ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ ರೆಪೊಸಿಟರಿಯು ಕೇವಲ id
ಪ್ರಾಪರ್ಟಿ ಹೊಂದಿರುವ ಎಂಟಿಟಿಗಳ ಮೇಲೆ ಮಾತ್ರ ಕಾರ್ಯನಿರ್ವಹಿಸಬಹುದೆಂದು ಖಚಿತಪಡಿಸುತ್ತದೆ. ಇದು ಡೇಟಾ ಸಮಗ್ರತೆ ಮತ್ತು ಸ್ಥಿರತೆಯನ್ನು ಕಾಪಾಡಿಕೊಳ್ಳಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಈ ಪ್ಯಾಟರ್ನ್ ವಿವಿಧ ಸ್ವರೂಪಗಳಲ್ಲಿ ಡೇಟಾವನ್ನು ನಿರ್ವಹಿಸಲು ಉಪಯುಕ್ತವಾಗಿದೆ, Product
ಇಂಟರ್ಫೇಸ್ನಲ್ಲಿ ವಿವಿಧ ಕರೆನ್ಸಿ ಪ್ರಕಾರಗಳನ್ನು ನಿಭಾಯಿಸುವ ಮೂಲಕ ಅಂತರರಾಷ್ಟ್ರೀಕರಣಕ್ಕೆ ಹೊಂದಿಕೊಳ್ಳುತ್ತದೆ.
ಜೆನೆರಿಕ್ ಪೇಲೋಡ್ಗಳೊಂದಿಗೆ ಈವೆಂಟ್ ಹ್ಯಾಂಡ್ಲಿಂಗ್
ಮತ್ತೊಂದು ಸಾಮಾನ್ಯ ಬಳಕೆಯ ಪ್ರಕರಣವೆಂದರೆ ಈವೆಂಟ್ ಹ್ಯಾಂಡ್ಲಿಂಗ್. ನೀವು ನಿರ್ದಿಷ್ಟ ಪೇಲೋಡ್ನೊಂದಿಗೆ ಜೆನೆರಿಕ್ ಈವೆಂಟ್ ಟೈಪ್ ಅನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಬಹುದು.
interface Event<T> {
type: string;
payload: T;
}
interface UserCreatedEventPayload {
userId: string;
email: string;
}
interface ProductPurchasedEventPayload {
productId: string;
quantity: number;
}
function handleEvent<T>(event: Event<T>): void {
console.log(`Handling event of type: ${event.type}`);
console.log(`Payload: ${JSON.stringify(event.payload)}`);
}
const userCreatedEvent: Event<UserCreatedEventPayload> = {
type: "user.created",
payload: { userId: "user123", email: "alice@example.com" },
};
const productPurchasedEvent: Event<ProductPurchasedEventPayload> = {
type: "product.purchased",
payload: { productId: "product456", quantity: 2 },
};
handleEvent(userCreatedEvent);
handleEvent(productPurchasedEvent);
ಇದು ನಿಮಗೆ ವಿವಿಧ ಪೇಲೋಡ್ ರಚನೆಗಳೊಂದಿಗೆ ವಿವಿಧ ಈವೆಂಟ್ ಟೈಪ್ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಲು ಅನುಮತಿಸುತ್ತದೆ, ಆದರೆ ಟೈಪ್ ಸುರಕ್ಷತೆಯನ್ನು ಕಾಪಾಡಿಕೊಳ್ಳುತ್ತದೆ. ಈ ರಚನೆಯನ್ನು ಸ್ಥಳೀಯ ಈವೆಂಟ್ ವಿವರಗಳನ್ನು ಬೆಂಬಲಿಸಲು ಸುಲಭವಾಗಿ ವಿಸ್ತರಿಸಬಹುದು, ಈವೆಂಟ್ ಪೇಲೋಡ್ನಲ್ಲಿ ಪ್ರಾದೇಶಿಕ ಆದ್ಯತೆಗಳನ್ನು ಅಳವಡಿಸಿಕೊಳ್ಳಬಹುದು, ಉದಾಹರಣೆಗೆ ವಿಭಿನ್ನ ದಿನಾಂಕ ಸ್ವರೂಪಗಳು ಅಥವಾ ಭಾಷಾ-ನಿರ್ದಿಷ್ಟ ವಿವರಣೆಗಳು.
ಜೆನೆರಿಕ್ ಡೇಟಾ ಟ್ರಾನ್ಸ್ಫರ್ಮೇಶನ್ ಪೈಪ್ಲೈನ್ ನಿರ್ಮಿಸುವುದು
ನೀವು ಡೇಟಾವನ್ನು ಒಂದು ಸ್ವರೂಪದಿಂದ ಇನ್ನೊಂದಕ್ಕೆ ಪರಿವರ್ತಿಸಬೇಕಾದ ಸನ್ನಿವೇಶವನ್ನು ಪರಿಗಣಿಸಿ. ಇನ್ಪುಟ್ ಮತ್ತು ಔಟ್ಪುಟ್ ಟೈಪ್ಗಳು ಟ್ರಾನ್ಸ್ಫರ್ಮೇಶನ್ ಫಂಕ್ಷನ್ಗಳೊಂದಿಗೆ ಹೊಂದಾಣಿಕೆಯಾಗುವುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ಬಳಸಿಕೊಂಡು ಜೆನೆರಿಕ್ ಡೇಟಾ ಟ್ರಾನ್ಸ್ಫರ್ಮೇಶನ್ ಪೈಪ್ಲೈನ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಬಹುದು.
interface DataTransformer<TInput, TOutput> {
transform(input: TInput): TOutput;
}
function processData<TInput, TOutput, TIntermediate>(
input: TInput,
transformer1: DataTransformer<TInput, TIntermediate>,
transformer2: DataTransformer<TIntermediate, TOutput>
): TOutput {
const intermediateData = transformer1.transform(input);
const outputData = transformer2.transform(intermediateData);
return outputData;
}
interface RawUserData {
firstName: string;
lastName: string;
}
interface UserData {
fullName: string;
email: string;
}
class RawToIntermediateTransformer implements DataTransformer<RawUserData, {name: string}> {
transform(input: RawUserData): {name: string} {
return { name: `${input.firstName} ${input.lastName}`};
}
}
class IntermediateToUserTransformer implements DataTransformer<{name: string}, UserData> {
transform(input: {name: string}): UserData {
return {fullName: input.name, email: `${input.name.replace(" ", ".")}@example.com`};
}
}
const rawData: RawUserData = { firstName: "John", lastName: "Doe" };
const userData: UserData = processData(
rawData,
new RawToIntermediateTransformer(),
new IntermediateToUserTransformer()
);
console.log(userData);
ಈ ಉದಾಹರಣೆಯಲ್ಲಿ, processData
ಫಂಕ್ಷನ್ ಒಂದು ಇನ್ಪುಟ್, ಎರಡು ಟ್ರಾನ್ಸ್ಫಾರ್ಮರ್ಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ ಮತ್ತು ಪರಿವರ್ತಿತ ಔಟ್ಪುಟ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ. ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ಗಳು ಮತ್ತು ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳು ಮೊದಲ ಟ್ರಾನ್ಸ್ಫಾರ್ಮರ್ನ ಔಟ್ಪುಟ್ ಎರಡನೇ ಟ್ರಾನ್ಸ್ಫಾರ್ಮರ್ನ ಇನ್ಪುಟ್ಗೆ ಹೊಂದಾಣಿಕೆಯಾಗುವುದನ್ನು ಖಚಿತಪಡಿಸುತ್ತವೆ, ಇದು ಟೈಪ್-ಸುರಕ್ಷಿತ ಪೈಪ್ಲೈನ್ ಅನ್ನು ರಚಿಸುತ್ತದೆ. ಈ ಪ್ಯಾಟರ್ನ್ ವಿಭಿನ್ನ ಫೀಲ್ಡ್ ಹೆಸರುಗಳು ಅಥವಾ ಡೇಟಾ ರಚನೆಗಳನ್ನು ಹೊಂದಿರುವ ಅಂತರರಾಷ್ಟ್ರೀಯ ಡೇಟಾ ಸೆಟ್ಗಳೊಂದಿಗೆ ವ್ಯವಹರಿಸುವಾಗ ಅಮೂಲ್ಯವಾಗಿರುತ್ತದೆ, ಏಕೆಂದರೆ ನೀವು ಪ್ರತಿ ಸ್ವರೂಪಕ್ಕಾಗಿ ನಿರ್ದಿಷ್ಟ ಟ್ರಾನ್ಸ್ಫಾರ್ಮರ್ಗಳನ್ನು ನಿರ್ಮಿಸಬಹುದು.
ಉತ್ತಮ ಅಭ್ಯಾಸಗಳು ಮತ್ತು ಪರಿಗಣನೆಗಳು
- ಆನುವಂಶಿಕತೆಗಿಂತ ಸಂಯೋಜನೆಗೆ ಆದ್ಯತೆ ನೀಡಿ: ಆನುವಂಶಿಕತೆಯು ಉಪಯುಕ್ತವಾಗಿದ್ದರೂ, ಹೆಚ್ಚು ಹೊಂದಿಕೊಳ್ಳುವಿಕೆ ಮತ್ತು ನಿರ್ವಹಣೆಗಾಗಿ ಸಂಯೋಜನೆ ಮತ್ತು ಇಂಟರ್ಫೇಸ್ಗಳಿಗೆ ಆದ್ಯತೆ ನೀಡಿ, ವಿಶೇಷವಾಗಿ ಸಂಕೀರ್ಣ ಟೈಪ್ ಸಂಬಂಧಗಳೊಂದಿಗೆ ವ್ಯವಹರಿಸುವಾಗ.
- ಟೈಪ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ವಿವೇಚನೆಯಿಂದ ಬಳಸಿ: ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ಗಳನ್ನು ಅತಿಯಾಗಿ ನಿರ್ಬಂಧಿಸಬೇಡಿ. ಅಗತ್ಯವಾದ ಟೈಪ್ ಸುರಕ್ಷತೆಯನ್ನು ಒದಗಿಸುವ ಅತ್ಯಂತ ಸಾಮಾನ್ಯ ಟೈಪ್ಗಳಿಗೆ ಶ್ರಮಿಸಿ.
- ಕಾರ್ಯಕ್ಷಮತೆಯ ಪರಿಣಾಮಗಳನ್ನು ಪರಿಗಣಿಸಿ: ಜೆನೆರಿಕ್ಸ್ನ ಅತಿಯಾದ ಬಳಕೆಯು ಕೆಲವೊಮ್ಮೆ ಕಾರ್ಯಕ್ಷಮತೆಯ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು. ಯಾವುದೇ ಅಡಚಣೆಗಳನ್ನು ಗುರುತಿಸಲು ನಿಮ್ಮ ಕೋಡ್ ಅನ್ನು ಪ್ರೊಫೈಲ್ ಮಾಡಿ.
- ನಿಮ್ಮ ಕೋಡ್ ಅನ್ನು ದಾಖಲಿಸಿ: ನಿಮ್ಮ ಜೆನೆರಿಕ್ ಟೈಪ್ಗಳು ಮತ್ತು ಟೈಪ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳ ಉದ್ದೇಶವನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ದಾಖಲಿಸಿ. ಇದು ನಿಮ್ಮ ಕೋಡ್ ಅನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಮತ್ತು ನಿರ್ವಹಿಸಲು ಸುಲಭಗೊಳಿಸುತ್ತದೆ.
- ಸಂಪೂರ್ಣವಾಗಿ ಪರೀಕ್ಷಿಸಿ: ನಿಮ್ಮ ಜೆನೆರಿಕ್ ಕೋಡ್ ವಿವಿಧ ಟೈಪ್ಗಳೊಂದಿಗೆ ನಿರೀಕ್ಷೆಯಂತೆ ವರ್ತಿಸುತ್ತದೆ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ಸಮಗ್ರ ಯೂನಿಟ್ ಪರೀಕ್ಷೆಗಳನ್ನು ಬರೆಯಿರಿ.
ತೀರ್ಮಾನ
ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ವೇರಿಯನ್ಸ್ ಅನೋಟೇಶನ್ಗಳನ್ನು (ಫಂಕ್ಷನ್ ಪ್ಯಾರಾಮೀಟರ್ ನಿಯಮಗಳ ಮೂಲಕ ಪರೋಕ್ಷವಾಗಿ) ಮತ್ತು ಟೈಪ್ ಪ್ಯಾರಾಮೀಟರ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ಮಾಸ್ಟರಿಂಗ್ ಮಾಡುವುದು ದೃಢವಾದ, ಹೊಂದಿಕೊಳ್ಳುವ ಮತ್ತು ನಿರ್ವಹಿಸಬಲ್ಲ ಕೋಡ್ ನಿರ್ಮಿಸಲು ಅತ್ಯಗತ್ಯ. ಕೋವೇರಿಯನ್ಸ್, ಕಾಂಟ್ರಾವೇರಿಯನ್ಸ್ ಮತ್ತು ಇನ್ವೇರಿಯನ್ಸ್ಗಳ ಪರಿಕಲ್ಪನೆಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವ ಮೂಲಕ ಮತ್ತು ಟೈಪ್ ಕನ್ಸ್ಟ್ರೈಂಟ್ಗಳನ್ನು ಪರಿಣಾಮಕಾರಿಯಾಗಿ ಬಳಸುವ ಮೂಲಕ, ನೀವು ಟೈಪ್-ಸುರಕ್ಷಿತ ಮತ್ತು ಮರುಬಳಕೆ ಮಾಡಬಹುದಾದ ಜೆನೆರಿಕ್ ಕೋಡ್ ಬರೆಯಬಹುದು. ಇಂದಿನ ಜಾಗತೀಕೃತ ಸಾಫ್ಟ್ವೇರ್ ಕ್ಷೇತ್ರದಲ್ಲಿ ಸಾಮಾನ್ಯವಾದಂತೆ, ವೈವಿಧ್ಯಮಯ ಡೇಟಾ ಪ್ರಕಾರಗಳನ್ನು ನಿರ್ವಹಿಸಬೇಕಾದ ಅಥವಾ ವಿಭಿನ್ನ ಪರಿಸರಗಳಿಗೆ ಹೊಂದಿಕೊಳ್ಳಬೇಕಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಅಭಿವೃದ್ಧಿಪಡಿಸುವಾಗ ಈ ತಂತ್ರಗಳು ವಿಶೇಷವಾಗಿ ಮೌಲ್ಯಯುತವಾಗಿವೆ. ಉತ್ತಮ ಅಭ್ಯಾಸಗಳನ್ನು ಪಾಲಿಸುವ ಮೂಲಕ ಮತ್ತು ನಿಮ್ಮ ಕೋಡ್ ಅನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಪರೀಕ್ಷಿಸುವ ಮೂಲಕ, ನೀವು ಟೈಪ್ಸ್ಕ್ರಿಪ್ಟ್ನ ಟೈಪ್ ಸಿಸ್ಟಮ್ನ ಸಂಪೂರ್ಣ ಸಾಮರ್ಥ್ಯವನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಬಹುದು ಮತ್ತು ಉತ್ತಮ ಗುಣಮಟ್ಟದ ಸಾಫ್ಟ್ವೇರ್ ಅನ್ನು ರಚಿಸಬಹುದು.