4.4 জেনেরিক কন্সট্রেইন্টস এবং keyof অপারেটর

জেনেরিক কন্সট্রেইন্টস হল একটি জেনেরিক ক্লাস বা ফাংশনে কোন কোন টাইপ ব্যবহার  করা যাবে সেটি নির্দিষ্ট করে দেওয়ার একটি উপায়। যেন একটি জেনেরিক ফাংশন বা ক্লাস জেনেরিক প্যারামিটারের নির্দিষ্ট কিছু প্রোপারটিস বা মেথড এক্সেস করতে পারে। যেমন একটি ফাংশন লেখা যাক যা একটি অ্যারের Length রিটার্ন করে,

				
					function getLength<T>(array: T[]): number {
  return array.length;
}
				
			

এই ফাংশনটি অ্যারে টাইপের জন্য কাজ করে কিন্তু অন্য কোন টাইপের জন্য কাজ করে না। আমরা যদি অন্য টাইপ পাস কারার চেষ্টা করি তাহলে কম্পাইলার এরকম কিছু এরর দেখাবে:

				
					let num = getLength(42); 
// Error: Argument of type 'number' is not assignable to parameter of type 'unknown[]'.
let str = getLength("hello"); 
// Error: Argument of type 'string' is not assignable to parameter of type 'unknown[]'.

				
			

এ সমস্যা সমাধানের জন্য আমরা extend কীওয়ার্ড  ব্যবহার  করতে পারি।

				
					function getLength<T extends any[]>(array: T): number {
  return array.length;
}
				
			

এখানে ফাংশনটি কেবল any[] টাইপে extend হওয়া টাইপ গ্রহণ করবে, অর্থাৎ এমন টাইপ যাতে ডট length প্রোপার্টি রয়েছে। অথবা আমরা একটি ইন্টারফেস তৈরি করতে পারি। যেমন:

				
					interface LengthWise {
   length: number;
}
 
function getLength<Type extends LengthWise>(arg: Type): Type {
   console.log(arg.length); 
   // Now we know it has a .length property, so no more error
   return arg;
}

getLength({ length: 10, value: 3 });
				
			

keyof অপারেটর কি?

জাভাস্ক্রিপ্টে আমরা খুব সহজে একটি অবজেক্ট এর কী (key ) এক্সেস করতে পারি Object.keys এটি ওই জাভাস্ক্রিপ্ট এর কী (key) গুলো একটি Array হিসেবে রিটার্ন করে।

				
					const user = {
  id: 666,
  name: "bytefer",
}
const keys = Object.keys(user); // ["id", "name"]
				
			

তবে টাইপস্ক্রিপ্টে  আমরা অবজেক্ট টাইপের কী (key) এইভাবে এক্সেস করতে পারবো না। আমাদের প্রয়োজন হবে keyof অপারেটর। keyof অপারেটর দ্বারা টাইপস্ক্রিপ্ট অবজেক্টের সকল কী (key) পাওয়া যাবে এবং এটির রিটার্ন টাইপ হচ্ছে ইউনিয়ন টাইপ।

				
					type User = {
  id: number;
  name: string;
}
type UserKeys = keyof User; // "id" | "name"
				
			

keyof অপারেটর কন্সট্রেইন্স এ কিভাবে কাজ করে?

আবার আমরা চাইলে একটি টাইপ প্যারামিটার ডিক্লেয়ার করতে পারি যা অন্য টাইপ প্যারামিটার দ্বারা সীমাবদ্ধ বা constrained । উদাহরণস্বরূপ, আমরা যদি  একটি অবজেক্টের প্রোপার্টি সেই প্রোপার্টির নাম দিয়ে এক্সেস করতে চাই এবং এইটা নিশ্চিত হতে চাই যে সে প্রোপার্টি  অবজেক্টে বিদ্যমান তখন আমরা দুটি টাইপের মাঝখানে constrain হিসেবে keyof টাইপ অপারেটর রাখতে পারি। keyof অপারেটর সে অবজেক্টের কী (key) গুলো  iterate করতে পারে। যেমন:

				
					function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
   return obj[key];
}
 
let x = { a: 1, b: 2, c: 3, d: 4 };
 
getProperty(x, "a");
getProperty(x, "m"); // Argument of type '"m"' is not assignable to parameter of type '"a" | "b" | "c" | "d"'.