দৈনন্দিন কোডের জন্য TypeScript জেনেরিকস: একটি ব্যবহারিক গাইড

Frontend2026-09-21TryQuickToolBox

আপনি এমন একটি ফাংশন লিখছেন যা যেকোনো টাইপের সাথে কাজ করে, কিন্তু আপনি টাইপ সুরক্ষা হারাতে চান না। আপনি any ব্যবহার করতে পারেন, কিন্তু তা TypeScript-এর উদ্দেশ্য ব্যর্থ করে। জেনেরিকস আপনাকে একাধিক টাইপের সাথে কাজ করে এমন কোড লিখতে দেয় যা টাইপ তথ্য সংরক্ষণ করে। এই গাইডটি দেখায় কীভাবে জিনিসগুলিকে জটিল না করে দৈনন্দিন কোডে জেনেরিকস ব্যবহার করবেন।

জেনেরিকস কী?

জেনেরিকস হলো পুনঃব্যবহারযোগ্য কম্পোনেন্ট তৈরি করার একটি উপায় যা একক টাইপের পরিবর্তে বিভিন্ন টাইপের সাথে কাজ করে। তারা আপনাকে ইনপুটের টাইপ ক্যাপচার করতে এবং আউটপুটে ব্যবহার করতে দেয়, নমনীয়তা ত্যাগ না করে টাইপ সুরক্ষা নিশ্চিত করে।

জেনেরিকসকে টাইপ প্যারামিটার হিসেবে ভাবুন। যেমন একটি ফাংশন ভ্যালু প্যারামিটার নেয়, একটি জেনেরিক ফাংশন টাইপ প্যারামিটার নেয়। উদাহরণস্বরূপ, আইডেন্টিটি ফাংশন:

function identity<T>(arg: T): T {
  return arg;
}

এখানে, T একটি টাইপ প্যারামিটার। যখন আপনি identity<string>("hello") কল করেন, TypeScript অনুমান করে যে T হলো string, এবং রিটার্ন টাইপ হলো string। যদি আপনি একটি সংখ্যা পাস করেন, এটি একটি সংখ্যা রিটার্ন করে। এটি any ব্যবহারের চেয়ে আরও সুনির্দিষ্ট।

কেন শুধু any ব্যবহার করবেন না?

any ব্যবহার টাইপ চেকিং নিষ্ক্রিয় করে। আপনি অটোকমপ্লিশন, রিফ্যাক্টরিং সাপোর্ট হারান, এবং কম্পাইলার ভুল ধরতে পারে না। জেনেরিকস আপনার কোডের মাধ্যমে টাইপ তথ্য প্রবাহিত রাখে, তাই আপনি নমনীয়তা এবং সুরক্ষা উভয়ই পান।

ব্যবহারিক ক্ষেত্রে জেনেরিক ফাংশন

একটি সাধারণ পরিস্থিতি দেখি: একটি ফাংশন যা একটি অ্যারের প্রথম উপাদান রিটার্ন করে।

function firstElement<T>(arr: T[]): T | undefined {
  return arr[0];
}

জেনেরিকস ছাড়া, আপনি function firstElement(arr: any[]): any লিখতে পারেন, যা টাইপ হারায়। জেনেরিকসের সাথে, যদি আপনি একটি string[] পাস করেন, রিটার্ন টাইপ হয় string | undefined।

আপনি একাধিক টাইপ প্যারামিটারও ব্যবহার করতে পারেন। উদাহরণস্বরূপ, একটি ফাংশন যা একটি কলব্যাক ব্যবহার করে একটি অ্যারে থেকে একটি নতুন অ্যারেতে ম্যাপ করে:

function map<T, U>(arr: T[], fn: (item: T) => U): U[] {
  return arr.map(fn);
}

এটি মূলত TypeScript-এর স্ট্যান্ডার্ড লাইব্রেরিতে Array.prototype.map যেভাবে টাইপ করা হয়েছে।

জেনেরিক ইন্টারফেস এবং টাইপ অ্যালিয়াস

জেনেরিকস শুধু ফাংশনে সীমাবদ্ধ নয়। আপনি পুনঃব্যবহারযোগ্য ডেটা স্ট্রাকচার সংজ্ঞায়িত করতে জেনেরিক ইন্টারফেস এবং টাইপ অ্যালিয়াস তৈরি করতে পারেন।

interface Box<T> {
  value: T;
}

const stringBox: Box<string> = { value: "hello" };
const numberBox: Box<number> = { value: 42 };

এটি API প্রতিক্রিয়া, স্টেট ম্যানেজমেন্ট, বা যেকোনো কন্টেইনার টাইপের জন্য উপযোগী।

আপনি ডিফল্ট টাইপও দিতে পারেন:

interface ApiResponse<T = unknown> {
  data: T;
  status: number;
}

এখন ApiResponse টাইপ আর্গুমেন্ট ছাড়া ডিফল্টভাবে unknown হয়।

জেনেরিক কনস্ট্রেইন্ট

কখনও কখনও আপনি জেনেরিকের সাথে ব্যবহার করা যেতে পারে এমন টাইপ সীমাবদ্ধ করতে চান। আপনি একটি কনস্ট্রেইন্ট যোগ করতে extends কীওয়ার্ড ব্যবহার করতে পারেন।

function getLength<T extends { length: number }>(arg: T): number {
  return arg.length;
}

এখন T-তে একটি length প্রপার্টি থাকতে হবে। আপনি getLength("hello") বা getLength([1,2,3]) কল করতে পারেন, কিন্তু getLength(42) নয়।

সাধারণ আকৃতি ভাগ করে নেয় এমন বস্তুর সাথে কাজ করার সময় কনস্ট্রেইন্ট শক্তিশালী।

ক্লাসের সাথে জেনেরিকস ব্যবহার

ক্লাসও জেনেরিক হতে পারে। একটি সাধারণ উদাহরণ হলো একটি জেনেরিক কালেকশন:

class Stack<T> {
  private items: T[] = [];

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T | undefined {
    return this.items.pop();
  }
}

const stack = new Stack<number>();
stack.push(1);
stack.push(2);
const popped = stack.pop(); // number | undefined

এটি নিশ্চিত করে যে একটি সংখ্যা স্ট্যাকে শুধুমাত্র সংখ্যা পুশ করা যায়।

বাস্তব-জগতের উদাহরণ: একটি টাইপ-সুরক্ষিত ইভেন্ট এমিটার

চলুন একটি সাধারণ ইভেন্ট এমিটার তৈরি করি যা ইভেন্ট নামগুলিকে পেলোড টাইপে ম্যাপ করতে জেনেরিকস ব্যবহার করে।

type EventMap = Record<string, any>;

class EventEmitter<T extends EventMap> {
  private listeners: { [K in keyof T]?: Array<(payload: T[K]) => void> } = {};

  on<K extends keyof T>(event: K, listener: (payload: T[K]) => void): void {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event]!.push(listener);
  }

  emit<K extends keyof T>(event: K, payload: T[K]): void {
    this.listeners[event]?.forEach(listener => listener(payload));
  }
}

// Usage
interface MyEvents {
  login: { userId: string };
  logout: { userId: string };
}

const emitter = new EventEmitter<MyEvents>();
emitter.on('login', (payload) => {
  console.log(payload.userId); // string
});
emitter.emit('login', { userId: '123' }); // OK
// emitter.emit('login', { userId: 123 }); // Error

এই প্যাটার্নটি আপনাকে ইভেন্ট নাম এবং পেলোডের জন্য সম্পূর্ণ টাইপ সুরক্ষা দেয়, রানটাইম ত্রুটি হ্রাস করে।

সাধারণ সমস্যা এবং সেরা অনুশীলন

তুলনা: জেনেরিকস বনাম any বনাম ইউনিয়ন টাইপ

পদ্ধতি টাইপ সুরক্ষা নমনীয়তা ব্যবহারের ক্ষেত্র
জেনেরিকস উচ্চ উচ্চ সংরক্ষিত টাইপ সহ পুনঃব্যবহারযোগ্য কম্পোনেন্ট
any নেই উচ্চ দ্রুত প্রোটোটাইপিং, JS মাইগ্রেশন
ইউনিয়ন টাইপ মাঝারি মাঝারি পরিচিত টাইপের সীমিত সেট

জেনেরিকস নমনীয়তা এবং সুরক্ষার মধ্যে ভারসাম্য বজায় রাখে, যা লাইব্রেরি এবং শেয়ারড ইউটিলিটির জন্য আদর্শ।

সাধারণ প্রশ্ন

কখন ইউনিয়ন টাইপের পরিবর্তে জেনেরিকস ব্যবহার করব?

যখন ইনপুট এবং আউটপুটের মধ্যে টাইপ সম্পর্ক গুরুত্বপূর্ণ তখন জেনেরিকস ব্যবহার করুন। ইউনিয়ন টাইপ হল যখন একটি মান নির্দিষ্ট টাইপের সেটের একটি হতে পারে, কিন্তু নির্দিষ্ট টাইপ অপারেশন জুড়ে সংরক্ষণ করার প্রয়োজন হয় না।

আমি কি অ্যারো ফাংশনের সাথে জেনেরিকস ব্যবহার করতে পারি?

হ্যাঁ, কিন্তু .tsx ফাইলে সিনট্যাক্স জটিল হতে পারে। আপনি JSX অস্পষ্টতা এড়াতে ট্রেইলিং কমা দিয়ে const identity = <T,>(arg: T): T => arg; লিখতে পারেন।

কীভাবে একটি জেনেরিককে শুধুমাত্র অবজেক্ট গ্রহণ করতে সীমাবদ্ধ করব?

T extends object বা T extends Record<string, unknown> ব্যবহার করুন যাতে T একটি অবজেক্ট টাইপ হয়।

জেনেরিকস TypeScript-এর টাইপ সিস্টেমের একটি ভিত্তি। আপনার দৈনন্দিন কোডে এগুলি ব্যবহার করে, আপনি নমনীয় এবং নিরাপদ উভয়ই ফাংশন, ইন্টারফেস এবং ক্লাস লিখতে পারেন। সাধারণ জেনেরিক ফাংশন দিয়ে শুরু করুন, তারপর প্রয়োজন অনুসারে ধীরে ধীরে কনস্ট্রেইন্ট এবং আরও জটিল প্যাটার্ন অন্তর্ভুক্ত করুন। আরও ডেভেলপার টুলের জন্য, আপনার JSON ডেটা দ্রুত যাচাই এবং ফরম্যাট করতে আমাদের JSON Formatter দেখুন।