TypeScript Constraints
TypeScript constraints ব্যবহার করা হয় জেনেরিক টাইপ ডিক্লারেশনে, যেটা জেনেরিক টাইপ আর্গুমেন্টগুলোর জন্য নির্দিষ্ট টাইপ সীমাবদ্ধ করে। কনস্ট্রেইন্টসের মাধ্যমে আপনি নির্দিষ্ট করতে পারেন যে একটি জেনেরিক টাইপ প্যারামিটারকে নির্দিষ্ট কোনো ইন্টারফেস ইমপ্লিমেন্ট করতে হবে, একটি নির্দিষ্ট মেথড থাকতে হবে, অথবা একটি নির্দিষ্ট ক্লাস এক্সটেন্ড করতে হবে। এটি টাইপ নিরাপত্তা নিশ্চিত করে এবং কোডের পূর্বাভাসযোগ্যতা বৃদ্ধি করে।
Generics use করলে অনেক flexibility পাই — কিন্তু কোনো কোনো সময় আমরা চাই “T অবশ্যই একটা নির্দিষ্ট টাইপের মধ্যেই হবে”।
মানে, আমরা generic টাইপের উপর শর্ত (condition) বসাতে পারি।
ধরেন, আমরা চাইছি যে student
দের তথ্যের সঙ্গে একটা course
যুক্ত করে দিতে।
এখন এই কাজটা করতে গেলে অবশ্যই আমাদের জানা লাগবে সেই student
এর name
, id
আর extra value থাকলেও সমস্যা নাই — কিন্তু name
আর id
অবশ্যই লাগবে।
এই রকম situation এ আমরা Generics এর সাথে constraint (extends
) ব্যবহার করতে পারি।
উদাহরণ:
const addCoursetostudent = <T,>(student: T) => {
const course = "Next Level Web Development";
return {
...student,
course,
};
};
ডাইনামিক টাইপ সহ জেনেরিক ফাংশন:
এখন আমরা কিছু শিক্ষার্থী যুক্ত করবো:
type Student = {
id: number;
name: string;
email: string;
devType: string;
haswatch: string;
};
const student1 = addCoursetostudent<Student>({
id: 4,
name: "Rahim",
email: "Rahim@gmail.com",
devType: "NLWD",
haswatch: "Apple",
});
const student2 = addCoursetostudent<Student>({
id: 5,
name: "Karim",
email: "Karim@gmail.com",
devType: "NLWD",
haswatch: "Samsung",
});
সমস্যা:
এখন তৃতীয় উদাহরণটি দেখি:
const student3 = addCoursetostudent<{ email: string }>({
email: "just@mail.com",
});
এখানে id
, name
বা অন্যান্য প্রয়োজনীয় ডাটা নেই, তাই আমরা তাকে শিক্ষার্থী হিসেবে সনাক্ত করতে পারছি না। আবার যদি এইভাবে দেওয়া হয়:
const student3 = addCoursetostudent<{ devType: string }>({ devType: "NLWD" });
এক্ষেত্রে ডাইনামিক টাইপ দেওয়া হলেও, শিক্ষার্থী বা অবজেক্ট হিসেবে সনাক্ত করা সম্ভব নয়। এই পরিস্থিতিতে কনস্ট্রেইন্টস ব্যবহার করে আমরা প্রয়োজনীয় ডাটা নির্ধারণ করতে পারি।
সমাধান: Constraints ব্যবহার
const addCoursetostudent = <
T extends { id: number; name: string; email: string }
>(
student: T
) => {
const course = "Next Level Web Development";
return {
...student,
course,
};
}; // Updated Function with Constraint
ভুল উদাহরণ:
const student3 = addCoursetostudent<{ devType: string }>({ devType: "NLWD" });
উপরের কোডে ত্রুটি দেখাবে কারণ প্রয়োজনীয় ডাটা দেওয়া হয়নি।
সঠিক উদাহরণ:
const student3 = addCoursetostudent<{
name: string;
email: string;
id: number;
}>({
id: 6,
name: "NLWD",
email: "nlwd@gmail.com",
});
এইভাবে, কনস্ট্রেইন্টস ব্যবহার করে আমরা নিশ্চিত করতে পারি যে শিক্ষার্থীর জন্য প্রাথমিক ডাটা অন্তত থাকতে হবে।
Example with Interface
উদাহরণ:
interface Student {
name: string;
id: number;
}
const addCourseToStudent = <T extends Student>(data: T) => {
const courseName = "Next Level Web Development";
return {
...data,
course: courseName,
};
};
const updatedStudent = addCourseToStudent({
name: "Hamim",
id: 101,
age: 18,
});
console.log(updatedStudent);
// Output:
// { name: 'Hamim', id: 101, age: 18, course: 'Next Level Web Development' }
ব্যাখ্যা:
🔹 এখানে আমরা Student
নামে একটি interface তৈরি করেছি যেখানে দুটি property আছে:
name
(string টাইপের)id
(number টাইপের)
🔹 তারপর একটি Generic Function addCourseToStudent
তৈরি করা হয়েছে, যেখানে <T extends Student>
লেখা আছে। এর মানে:
- ফাংশনে যে ডেটা পাঠাবো, তাতে
name
এবংid
থাকা বাধ্যতামূলক। - তবে এই object এ অতিরিক্ত প্রপার্টি (যেমন
age
) থাকলেও সমস্যা নেই।
🔹 ফাংশনটি প্রাপ্ত ডেটার সাথে একটি নতুন property (course
) যুক্ত করছে, যার মান Next Level Web Development
।
Constraint এর সুবিধা: ➡️ এইভাবে আমরা dynamic object পাঠাতে পারি যেটাতে
অতিরিক্ত প্রপার্টি (যেমন age
) থাকলেও সমস্যা নেই, কিন্তু name
এবং id
থাকতে হবে — এটাকেই বলা হয় Constraint।