ગુજરાતી

વધુ લવચીક, સુરક્ષિત અને જાળવણી યોગ્ય કોડ બનાવવા માટે ટાઇપસ્ક્રિપ્ટના વેરિયન્સ એનોટેશન્સ અને ટાઇપ પેરામીટર કન્સ્ટ્રેઇન્ટ્સની શક્તિને અનલૉક કરો. વ્યવહારુ ઉદાહરણો સાથે ઊંડાણપૂર્વકનો અભ્યાસ.

ટાઇપસ્ક્રિપ્ટ વેરિયન્સ એનોટેશન્સ: મજબૂત કોડ માટે ટાઇપ પેરામીટર કન્સ્ટ્રેઇન્ટ્સમાં નિપુણતા

ટાઇપસ્ક્રિપ્ટ, જે જાવાસ્ક્રિપ્ટનું સુપરસબસેટ છે, તે સ્ટેટિક ટાઇપિંગ પ્રદાન કરે છે, જે કોડની વિશ્વસનીયતા અને જાળવણીક્ષમતામાં વધારો કરે છે. ટાઇપસ્ક્રિપ્ટની વધુ અદ્યતન, છતાં શક્તિશાળી, સુવિધાઓમાંની એક ટાઇપ પેરામીટર કન્સ્ટ્રેઇન્ટ્સ સાથે વેરિયન્સ એનોટેશન્સ માટે તેનો સપોર્ટ છે. ખરેખર મજબૂત અને લવચીક જેનરિક કોડ લખવા માટે આ ખ્યાલોને સમજવું મહત્વપૂર્ણ છે. આ બ્લોગ પોસ્ટ વેરિયન્સ, કોવેરિયન્સ, કોન્ટ્રાવેરિયન્સ અને ઇનવેરિયન્સમાં ઊંડાણપૂર્વક જશે, અને સુરક્ષિત અને વધુ ફરીથી વાપરી શકાય તેવા કમ્પોનન્ટ્સ બનાવવા માટે ટાઇપ પેરામીટર કન્સ્ટ્રેઇન્ટ્સનો અસરકારક રીતે કેવી રીતે ઉપયોગ કરવો તે સમજાવશે.

વેરિયન્સને સમજવું

વેરિયન્સ વર્ણવે છે કે પ્રકારો વચ્ચેનો સબટાઇપ સંબંધ કન્સ્ટ્રક્ટેડ પ્રકારો (દા.ત., જેનરિક પ્રકારો) વચ્ચેના સબટાઇપ સંબંધને કેવી રીતે અસર કરે છે. ચાલો મુખ્ય શબ્દોને સમજીએ:

આને એક ઉદાહરણ સાથે યાદ રાખવું સૌથી સરળ છે: એક ફેક્ટરીનો વિચાર કરો જે કૂતરાના કોલર બનાવે છે. જો કોઈ કોવેરિયન્ટ ફેક્ટરી કૂતરા માટે કોલર બનાવી શકે, તો તે તમામ પ્રકારના પ્રાણીઓ માટે કોલર બનાવી શકે છે, જે સબટાઇપિંગ સંબંધને જાળવી રાખે છે. એક કોન્ટ્રાવેરિયન્ટ ફેક્ટરી એવી છે જે કોઈપણ પ્રકારના પ્રાણીઓના કોલરને *ઉપયોગ* કરી શકે છે, જો તે કૂતરાના કોલરનો ઉપયોગ કરી શકે. જો ફેક્ટરી ફક્ત કૂતરાના કોલર સાથે જ કામ કરી શકે અને બીજું કંઈ નહીં, તો તે પ્રાણીના પ્રકાર માટે ઇનવેરિયન્ટ છે.

વેરિયન્સ શા માટે મહત્વનું છે?

ટાઇપ-સેફ કોડ લખવા માટે વેરિયન્સને સમજવું મહત્વપૂર્ણ છે, ખાસ કરીને જ્યારે જેનરિક્સ સાથે કામ કરતા હોય. કોવેરિયન્સ અથવા કોન્ટ્રાવેરિયન્સને ખોટી રીતે માની લેવાથી રનટાઇમ એરર્સ થઈ શકે છે જેને ટાઇપસ્ક્રિપ્ટની ટાઇપ સિસ્ટમ રોકવા માટે બનાવવામાં આવી છે. આ ખામીયુક્ત ઉદાહરણનો વિચાર કરો (જાવાસ્ક્રિપ્ટમાં, પરંતુ ખ્યાલને સમજાવવા માટે):

// જાવાસ્ક્રિપ્ટ ઉદાહરણ (ફક્ત દૃષ્ટાંત માટે, ટાઇપસ્ક્રિપ્ટ નહીં)
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); // કામ કરે છે પરંતુ meow નહીં કરે

let mittens: Cat = { name: "Mittens", meow: () => {console.log("Mittens meows");}};

feed(mittens); // આ પણ કામ કરે છે, અને વાસ્તવિક ફંક્શનના આધારે meow કરી *શકે છે*.

આ ઉદાહરણમાં, 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; અસાઇનમેન્ટ માન્ય છે.

એરે અને જેનરિક્સ: ઇનવેરિયન્સ (મોટાભાગે)

ટાઇપસ્ક્રિપ્ટ એરે અને મોટાભાગના જેનરિક પ્રકારોને ડિફૉલ્ટ રૂપે ઇનવેરિયન્ટ તરીકે માને છે. આનો અર્થ એ છે કે Array<Cat> ને Array<Animal> નો સબટાઇપ માનવામાં આવતો *નથી*, ભલે CatAnimal ને વિસ્તૃત કરતું હોય. આ સંભવિત રનટાઇમ એરર્સને રોકવા માટે એક ઇરાદાપૂર્વકની ડિઝાઇન પસંદગી છે. જ્યારે અન્ય ઘણી ભાષાઓમાં એરે કોવેરિયન્ટ હોય તેવું *વર્તન* કરે છે, ટાઇપસ્ક્રિપ્ટ તેમને સુરક્ષા માટે ઇનવેરિયન્ટ બનાવે છે.

let animals: Animal[] = [{ name: "Generic Animal" }];
let cats: Cat[] = [{ name: "Whiskers", meow: () => { console.log("Whiskers meows"); } }];

// એરર: 'Cat[]' પ્રકાર 'Animal[]' પ્રકારને અસાઇન કરી શકાતો નથી.
// 'Cat' પ્રકાર 'Animal' પ્રકારને અસાઇન કરી શકાતો નથી.
// 'Animal' પ્રકારમાં 'meow' પ્રોપર્ટી ખૂટે છે પરંતુ '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; અસાઇનમેન્ટને મંજૂરી આપવી અસુરક્ષિત રહેશે કારણ કે તમે પછી animals એરેમાં એક જેનરિક Animal ઉમેરી શકો છો, જે 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 ફંક્શન એક ઇનપુટ, બે ટ્રાન્સફોર્મર લે છે અને રૂપાંતરિત આઉટપુટ રિટર્ન કરે છે. ટાઇપ પેરામીટર્સ અને કન્સ્ટ્રેઇન્ટ્સ એ સુનિશ્ચિત કરે છે કે પ્રથમ ટ્રાન્સફોર્મરનું આઉટપુટ બીજા ટ્રાન્સફોર્મરના ઇનપુટ સાથે સુસંગત છે, જે ટાઇપ-સેફ પાઇપલાઇન બનાવે છે. આ પેટર્ન આંતરરાષ્ટ્રીય ડેટા સેટ્સ સાથે કામ કરતી વખતે અમૂલ્ય હોઈ શકે છે જેમાં અલગ-અલગ ફીલ્ડ નામો અથવા ડેટા સ્ટ્રક્ચર્સ હોય છે, કારણ કે તમે દરેક ફોર્મેટ માટે વિશિષ્ટ ટ્રાન્સફોર્મર બનાવી શકો છો.

શ્રેષ્ઠ પદ્ધતિઓ અને વિચારણાઓ

નિષ્કર્ષ

મજબૂત, લવચીક અને જાળવણીક્ષમ કોડ બનાવવા માટે ટાઇપસ્ક્રિપ્ટના વેરિયન્સ એનોટેશન્સ (ગર્ભિત રીતે ફંક્શન પેરામીટર નિયમો દ્વારા) અને ટાઇપ પેરામીટર કન્સ્ટ્રેઇન્ટ્સમાં નિપુણતા મેળવવી આવશ્યક છે. કોવેરિયન્સ, કોન્ટ્રાવેરિયન્સ અને ઇનવેરિયન્સના ખ્યાલોને સમજીને અને ટાઇપ કન્સ્ટ્રેઇન્ટ્સનો અસરકારક રીતે ઉપયોગ કરીને, તમે એવો જેનરિક કોડ લખી શકો છો જે ટાઇપ-સેફ અને ફરીથી વાપરી શકાય તેવો બંને હોય. આ તકનીકો ખાસ કરીને એવી એપ્લિકેશનો વિકસાવતી વખતે મૂલ્યવાન છે કે જેને વિવિધ ડેટા પ્રકારોને હેન્ડલ કરવાની જરૂર હોય અથવા વિવિધ વાતાવરણને અનુકૂલન કરવાની જરૂર હોય, જેમ કે આજના વૈશ્વિકીકૃત સોફ્ટવેર લેન્ડસ્કેપમાં સામાન્ય છે. શ્રેષ્ઠ પદ્ધતિઓનું પાલન કરીને અને તમારા કોડનું સંપૂર્ણ પરીક્ષણ કરીને, તમે ટાઇપસ્ક્રિપ્ટની ટાઇપ સિસ્ટમની સંપૂર્ણ સંભાવનાને અનલૉક કરી શકો છો અને ઉચ્ચ-ગુણવત્તાવાળા સોફ્ટવેર બનાવી શકો છો.