TypeScript এ Advanced Types (উন্নত টাইপ) এর সাহায্যে আপনি আরও জটিল এবং শক্তিশালী টাইপ সিস্টেম তৈরি করতে পারেন। এগুলি টাইপের মধ্যে সম্পর্ক স্থাপন, বিভিন্ন টাইপের একত্রিত ব্যবহার, এবং টাইপের নিখুঁত কাস্টমাইজেশন করার সুযোগ দেয়। TypeScript এ বেশ কিছু উন্নত টাইপ রয়েছে যা আপনাকে টাইপ নিরাপত্তা বজায় রাখতে এবং কোড আরও শক্তিশালী করতে সাহায্য করে।
এখানে TypeScript এর কিছু Advanced Types সম্পর্কে বিস্তারিত আলোচনা করা হলো।
১. ইন্টারসেকশন টাইপ (Intersection Types)
ইন্টারসেকশন টাইপ ব্যবহার করে আপনি একাধিক টাইপকে একত্রিত করতে পারেন। এতে আপনি একাধিক টাইপের সব বৈশিষ্ট্য একসাথে ব্যবহার করতে পারবেন। ইন্টারসেকশন টাইপ সাধারণত & অপারেটর দিয়ে প্রকাশ করা হয়।
উদাহরণ:
interface Person {
name: string;
age: number;
}
interface Employee {
jobTitle: string;
salary: number;
}
type EmployeePerson = Person & Employee;
const employee: EmployeePerson = {
name: "John",
age: 30,
jobTitle: "Software Developer",
salary: 50000
};
এখানে EmployeePerson টাইপটি Person এবং Employee ইন্টারফেসের সমস্ত প্রপার্টি একত্রিত করেছে। এটি name, age, jobTitle, এবং salary সবকিছু ধারণ করে।
২. ইউনিয়ন টাইপ (Union Types)
ইউনিয়ন টাইপ একাধিক টাইপের মধ্যে যেকোনো একটি টাইপ গ্রহণ করতে সক্ষম হয়। এটি | (পাইপ) অপারেটর দিয়ে প্রকাশ করা হয়। এটি সাধারণত বিভিন্ন ধরনের মান গ্রহণ করতে ব্যবহৃত হয়।
উদাহরণ:
function printId(id: string | number) {
console.log(`Your ID is: ${id}`);
}
printId("ABC123"); // সঠিক
printId(12345); // সঠিক
এখানে id প্যারামিটারটি string অথবা number হতে পারে, যা string | number টাইপ দিয়ে নির্ধারণ করা হয়েছে।
৩. টাইপ গার্ড (Type Guards)
টাইপ গার্ড এমন একটি টেকনিক যা TypeScript কে বলে দেয় একটি নির্দিষ্ট টাইপের সাথে কাজ করার সময় কীভাবে আচরণ করতে হবে। এটি ব্যবহার করে আপনি টাইপের নির্দিষ্ট শাখায় প্রবেশ করতে পারেন।
উদাহরণ:
function isString(value: string | number): value is string {
return typeof value === "string";
}
function greet(value: string | number) {
if (isString(value)) {
console.log(`Hello, ${value}!`); // value is now treated as a string
} else {
console.log(`Your ID is: ${value}`); // value is treated as a number
}
}
greet("Alice");
greet(123);
এখানে isString একটি টাইপ গার্ড ফাংশন যা TypeScript কে বলে দেয় যখন value একটি string, তখন তাকে string হিসেবে ধরতে।
৪. ম্যাপড টাইপ (Mapped Types)
ম্যাপড টাইপ এর সাহায্যে আপনি একটি টাইপের সমস্ত প্রপার্টি বা অ্যাট্রিবিউটের উপর কিছু অপারেশন করতে পারেন। এটি একটি টাইপের প্রতিটি প্রপার্টির উপর নির্দিষ্ট পরিবর্তন বা কাস্টমাইজেশন করতে ব্যবহৃত হয়।
উদাহরণ:
type ReadOnly<T> = {
readonly [K in keyof T]: T[K];
};
interface Person {
name: string;
age: number;
}
const person: ReadOnly<Person> = {
name: "Alice",
age: 30
};
person.name = "Bob"; // ত্রুটি: name প্রপার্টি read-only
এখানে ReadOnly একটি ম্যাপড টাইপ যা যে কোন টাইপের সব প্রপার্টিকে readonly করে দেয়, অর্থাৎ আপনি তাদের মান পরিবর্তন করতে পারবেন না।
৫. কন্ডিশনাল টাইপ (Conditional Types)
কন্ডিশনাল টাইপ টাইপের মধ্যে একটি শর্ত প্রয়োগ করে নির্দিষ্ট টাইপ তৈরি করতে সাহায্য করে। এটি extends এবং infer কিওয়ার্ড ব্যবহার করে তৈরি করা হয়।
উদাহরণ:
type IsString<T> = T extends string ? "Yes" : "No";
type Test1 = IsString<string>; // "Yes"
type Test2 = IsString<number>; // "No"
এখানে IsString টাইপটি T টাইপটি string হলে "Yes" রিটার্ন করবে, অন্যথায় "No" রিটার্ন করবে।
৬. ইনডেক্স সাইনেচার (Index Signatures)
ইনডেক্স সাইনেচার ব্যবহার করে আপনি অবজেক্টে ডাইনামিক প্রপার্টি সংজ্ঞায়িত করতে পারেন। এর মাধ্যমে একটি অবজেক্টে অজানা প্রপার্টি টাইপ সেট করা সম্ভব।
উদাহরণ:
interface Dictionary {
[key: string]: number;
}
const dict: Dictionary = {
apple: 10,
banana: 20
};
console.log(dict["apple"]); // 10
এখানে Dictionary ইন্টারফেসটি string কী এবং number ভ্যালু সহ একটি অবজেক্ট তৈরির অনুমতি দেয়।
৭. ডিপ পিক (Deep Pick)
ডিপ পিক একটি বিশেষ ধরনের টাইপ অপারেশন, যা নির্দিষ্ট একটি অবজেক্টের গভীরে (nested) প্যারামিটার বা প্রপার্টি নির্বাচন করতে সাহায্য করে।
উদাহরণ:
type DeepPick<T, K extends keyof T> = K extends string ? T[K] : never;
interface Nested {
user: {
name: string;
age: number;
};
}
type NameType = DeepPick<Nested, "user">; // { name: string; age: number }
এখানে DeepPick টাইপটি গভীর অবজেক্টের একটি নির্দিষ্ট প্রপার্টি বা প্যারামিটার থেকে টাইপ পিক করতে সাহায্য করেছে।
৮. এগজাম্পল টিউটোরিয়াল
এখানে আমরা একটি জেনেরিক্স এবং ইন্টারসেকশন টাইপ ব্যবহার করে একটি ছোট অ্যাপ্লিকেশন তৈরি করতে পারি।
interface User {
id: number;
name: string;
}
interface Admin {
adminLevel: number;
}
type AdminUser = User & Admin;
function createAdminUser(user: AdminUser) {
console.log(`${user.name} is an admin with level ${user.adminLevel}`);
}
const adminUser: AdminUser = {
id: 1,
name: "Alice",
adminLevel: 5
};
createAdminUser(adminUser);
এখানে আমরা AdminUser টাইপটি User এবং Admin টাইপের ইন্টারসেকশন হিসেবে তৈরি করেছি, এবং পরে এটি createAdminUser ফাংশনে ব্যবহার করেছি।
সারাংশ
TypeScript এর উন্নত টাইপ সিস্টেম বিভিন্ন শক্তিশালী বৈশিষ্ট্য প্রদান করে যা আপনার কোডকে আরও কার্যকরী, টাইপ-সেফ, এবং পুনঃব্যবহারযোগ্য করে তোলে। ইন্টারসেকশন টাইপ, ইউনিয়ন টাইপ, টাইপ গার্ড, ম্যাপড টাইপ, কন্ডিশনাল টাইপ, ইনডেক্স সাইনেচার, ডিপ পিক এবং জেনেরিক্স ব্যবহার করে আপনি টাইপ নিরাপত্তা বজায় রেখে আরও জটিল এবং ডাইনামিক অ্যাপ্লিকেশন তৈরি করতে পারেন।
TypeScript এ Intersection Types এবং Union Types দুটি গুরুত্বপূর্ণ ধারণা যা ডেটা টাইপের সংমিশ্রণ এবং একাধিক টাইপের মধ্যে কাজ করার ক্ষমতা প্রদান করে। এগুলি টাইপ সিস্টেমের ফ্লেক্সিবিলিটি বাড়ায় এবং বিভিন্ন ধরনের মানের মধ্যে সম্পর্ক বা যোগসূত্র স্থাপন করতে সাহায্য করে।
১. Union Types
Union Types আপনাকে একাধিক টাইপের মধ্যে নির্বাচন করতে দেয়, অর্থাৎ একটি ভ্যারিয়েবল একাধিক টাইপের মান ধারণ করতে পারে। এটি | (পাইপ) চিহ্ন দিয়ে দুটি বা তার বেশি টাইপকে একত্রিত করা হয়।
উদাহরণ: Union Types
let value: string | number;
value = "Hello"; // Valid
value = 42; // Valid
value = true; // Error: boolean is not assignable to 'string | number'
এখানে:
valueভ্যারিয়েবলটিstringঅথবাnumberটাইপের যে কোনো মান গ্রহণ করতে পারে। এটিstring | numberটাইপ দ্বারা সংজ্ঞায়িত।- তবে এটি যদি
booleanটাইপের মান গ্রহণ করার চেষ্টা করা হয়, তখন ত্রুটি হবে কারণbooleanএই ইউনিয়ন টাইপে অন্তর্ভুক্ত নয়।
আরেকটি উদাহরণ:
function display(value: string | number) {
console.log(value);
}
display("Hello, World!"); // Output: Hello, World!
display(100); // Output: 100
এখানে:
displayফাংশনটিstringঅথবাnumberটাইপের প্যারামিটার নেয় এবং সেটি কনসোলে প্রিন্ট করে।
২. Intersection Types
Intersection Types আপনাকে একাধিক টাইপকে একত্রিত করতে দেয়, অর্থাৎ একটি ভ্যারিয়েবল একাধিক টাইপের সমস্ত বৈশিষ্ট্য ধারণ করতে পারে। এটি & (অ্যাম্পারস্যান্ড) চিহ্ন দিয়ে বিভিন্ন টাইপকে একত্রিত করা হয়।
উদাহরণ: Intersection Types
interface Person {
name: string;
age: number;
}
interface Address {
street: string;
city: string;
}
type PersonWithAddress = Person & Address;
const individual: PersonWithAddress = {
name: "John",
age: 30,
street: "123 Main St",
city: "New York",
};
এখানে:
PersonএবংAddressদুটি আলাদা ইন্টারফেস এবংPersonWithAddressএকটি নতুন টাইপ যাPersonএবংAddressইন্টারফেসের সব বৈশিষ্ট্য ধারণ করে।individualভ্যারিয়েবলটিPersonWithAddressটাইপের একটি মান ধারণ করছে, যেখানেname,age,street, এবংcityসমস্ত প্রোপার্টি থাকতে হবে।
আরেকটি উদাহরণ:
interface Employee {
id: number;
department: string;
}
interface Manager {
level: string;
teamSize: number;
}
type ManagerWithEmployee = Employee & Manager;
const manager: ManagerWithEmployee = {
id: 101,
department: "HR",
level: "Senior",
teamSize: 10,
};
এখানে:
ManagerWithEmployeeএকটিEmployeeএবংManagerটাইপের মিশ্রণ, যা উভয়ের সব বৈশিষ্ট্য ধারণ করে।
৩. Union Types এবং Intersection Types এর পার্থক্য
Union Types:
|চিহ্ন দিয়ে একাধিক টাইপের মধ্যে নির্বাচন করা যায়।- একটি ভ্যারিয়েবল একটি টাইপের মধ্যে সীমাবদ্ধ থাকে, তবে সেটি বিভিন্ন টাইপের মান গ্রহণ করতে পারে।
- এটি একাধিক সম্ভাব্য মানের মধ্যে একটিকে নির্বাচন করার সুযোগ প্রদান করে।
উদাহরণ:
let value: string | number;
Intersection Types:
&চিহ্ন দিয়ে একাধিক টাইপের বৈশিষ্ট্যগুলিকে একত্রিত করা হয়।- একটি ভ্যারিয়েবল সমস্ত টাইপের বৈশিষ্ট্য ধারণ করতে সক্ষম হয়। এটি টাইপগুলির মিশ্রণ।
- Intersection types সাধারণত আরও শক্তিশালী এবং কম্পোজেবল, যেখানে একাধিক টাইপের বৈশিষ্ট্যগুলির সমন্বয়ে একটি নতুন টাইপ তৈরি হয়।
উদাহরণ:
type PersonWithAddress = Person & Address;
৪. Union এবং Intersection Types এর ব্যবহার
যখন Union Types ব্যবহার করবেন:
- যখন আপনার ভ্যারিয়েবলটি একাধিক টাইপের মধ্যে কোন একটি ধরতে পারে, এবং আপনাকে তাদের মধ্যে যেকোনো একটিকে গ্রহণ করতে হবে।
- উদাহরণস্বরূপ, যখন আপনি একটি ভ্যারিয়েবল যা স্ট্রিং বা সংখ্যার মধ্যে হতে পারে, প্রক্রিয়া করছেন।
যখন Intersection Types ব্যবহার করবেন:
- যখন আপনার টাইপগুলি একত্রিত করতে চান এবং আপনাকে তাদের সব বৈশিষ্ট্য রাখতে হবে।
- উদাহরণস্বরূপ, যদি আপনি এমন একটি টাইপ তৈরি করতে চান যা একাধিক ইন্টারফেসের সমস্ত বৈশিষ্ট্য ধারণ করে।
সারাংশ
TypeScript এর Union Types এবং Intersection Types অত্যন্ত শক্তিশালী টাইপিং কৌশল, যা ডেটার সাথে কার্যকরভাবে কাজ করার জন্য দারুণ উপকারী। Union types বিভিন্ন সম্ভাব্য টাইপের মধ্যে একটি নির্বাচন করার সুযোগ দেয়, যেখানে Intersection types বিভিন্ন টাইপের বৈশিষ্ট্যগুলো একত্রিত করে একটি শক্তিশালী নতুন টাইপ তৈরি করে।
TypeScript-এ Conditional Types একটি শক্তিশালী ফিচার, যা টাইপ সিস্টেমের মধ্যে শর্তসাপেক্ষ (conditional) লজিক প্রয়োগ করতে দেয়। এটি আপনার কোডে আরও নমনীয়তা এবং ডায়নামিক টাইপ ব্যবহারের সুযোগ সৃষ্টি করে। Conditional Types এর মাধ্যমে আপনি টাইপের মধ্যে শর্ত নির্ধারণ করতে পারেন এবং এই শর্তের ভিত্তিতে টাইপ চয়েজ করতে পারেন।
Conditional Types মূলত extends এবং infer কিওয়ার্ড ব্যবহার করে কাজ করে। এটি টাইপকে একটি শর্তের ওপর নির্ভর করে পরিবর্তন করতে সক্ষম।
১. Conditional Types এর সাধারণ গঠন
Conditional Types এর সাধারণ সিনট্যাক্স কিছুটা এইরকম:
T extends U ? X : Y
এখানে:
Tহলো প্রথম টাইপUহলো দ্বিতীয় টাইপXহলো শর্ত সত্য হলে যে টাইপ রিটার্ন করা হবেYহলো শর্ত মিথ্যা হলে যে টাইপ রিটার্ন করা হবে
এই গঠনটি পড়লে এটা বোঝা যায় যে, যদি টাইপ T টাইপ U কে এক্সটেন্ড (বা সাপোর্ট) করে, তবে টাইপ X প্রদান করা হবে, অন্যথায় টাইপ Y প্রদান করা হবে।
২. Conditional Types এর উদাহরণ
১. বেসিক Conditional Type
ধরা যাক, আমাদের একটি টাইপ রয়েছে যা টাইপ T কে অন্য একটি টাইপ U এর সাথে তুলনা করবে এবং তার উপর ভিত্তি করে কিছু কাজ করবে।
type IsString<T> = T extends string ? "Yes" : "No";
let result1: IsString<string> = "Yes"; // এটি সঠিক
let result2: IsString<number> = "No"; // এটি সঠিক
এখানে IsString একটি টাইপ ডিফিনিশন যা চেক করে যে T টাইপটি string টাইপকে এক্সটেন্ড করে কিনা। যদি T টাইপ string হয়, তবে "Yes" রিটার্ন হবে, অন্যথায় "No"।
২. নেস্টেড Conditional Types
Conditional Types বিভিন্ন জায়গায় নেস্টেড (nested) হতে পারে। এটি আরও জটিল শর্ত এবং টাইপ নির্ধারণ করতে সহায়তা করে।
type IsStringOrNumber<T> = T extends string ? "String" : T extends number ? "Number" : "Other";
let result1: IsStringOrNumber<string> = "String"; // এটি সঠিক
let result2: IsStringOrNumber<number> = "Number"; // এটি সঠিক
let result3: IsStringOrNumber<boolean> = "Other"; // এটি সঠিক
এখানে, প্রথমে চেক করা হচ্ছে T টাইপ যদি string হয় তবে "String" রিটার্ন হবে, আর যদি T টাইপ number হয়, তবে "Number" রিটার্ন হবে, অন্যথায় "Other"।
৩. Infer কিওয়ার্ড ব্যবহার করা
infer কিওয়ার্ড ব্যবহার করে টাইপের মধ্যে অন্তর্নিহিত টাইপ নির্ধারণ করতে পারবেন। এটি সাধারণত ঐক্যফল (tuple) বা ফাংশনের রিটার্ন টাইপের মতো কেসে ব্যবহৃত হয়।
উদাহরণ:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type Example = ReturnType<() => string>; // Example হবে string
এখানে, ReturnType টাইপটি চেক করে যে যদি টাইপ T একটি ফাংশন হয়, তবে তার রিটার্ন টাইপ R থাকবে, অন্যথায় never।
৪. ডিস্ট্রিবিউটেড Conditional Types
TypeScript-এ যখন Conditional Types অ্যারে বা ইউনিয়ন টাইপে প্রয়োগ করা হয়, তখন এগুলি ডিস্ট্রিবিউটেড (distributed) হয়, অর্থাৎ, প্রতিটি উপাদানের জন্য আলাদাভাবে শর্ত প্রয়োগ করা হয়।
উদাহরণ:
type IsString<T> = T extends string ? "Yes" : "No";
type Test1 = IsString<string | number>; // "Yes" | "No"
এখানে, IsString টাইপটি ইউনিয়ন টাইপ string | number এর প্রতিটি উপাদানের জন্য আলাদাভাবে পরীক্ষা করা হয়েছে। তাই, ফলস্বরূপ Test1 টাইপ Yes | No হবে।
৫. Conditional Types এবং কন্ডিশনাল গারান্টি
Conditional Types আপনার কোডে টাইপ সেফটি নিশ্চিত করতে সাহায্য করে। উদাহরণস্বরূপ, যদি আপনি কোনো জেনেরিক টাইপ বা কন্ডিশনাল টাইপ ব্যবহার করেন এবং কিছু বিশেষ শর্তে একটি টাইপ প্রদান করেন, তবে TypeScript স্বয়ংক্রিয়ভাবে টাইপ সঠিকতার গ্যারান্টি দেবে।
উদাহরণ:
type IsArray<T> = T extends any[] ? "Array" : "Not Array";
let arrCheck: IsArray<number[]> = "Array"; // সঠিক
let notArrCheck: IsArray<string> = "Not Array"; // সঠিক
এখানে, IsArray টাইপ চেক করে যে T টাইপটি একটি অ্যারে কিনা। যদি T টাইপ একটি অ্যারে হয়, তবে "Array" রিটার্ন হবে, অন্যথায় "Not Array" রিটার্ন হবে।
TypeScript এর Conditional Types আপনাকে টাইপের ওপর শর্তযুক্ত লজিক প্রয়োগ করতে সহায়তা করে এবং এটি কোডের স্বচ্ছতা এবং টাইপ সেফটি বৃদ্ধি করে। আপনি Conditional Types ব্যবহার করে ডায়নামিক টাইপ চেকিং, টাইপ গ্যারান্টি এবং আরও উন্নত টাইপ সিস্টেম তৈরি করতে পারেন। TypeScript-এ Conditional Types এর সঠিক ব্যবহার কোডের রক্ষণাবেক্ষণ সহজতর করে এবং টাইপ সংক্রান্ত ত্রুটি হ্রাস করতে সাহায্য করে।
Mapped Types TypeScript এর একটি শক্তিশালী ফিচার যা আপনাকে অবজেক্ট টাইপের প্রতিটি প্রপার্টির জন্য একটি নতুন টাইপ তৈরি করতে সহায়তা করে। এটি টাইপ প্রোগ্রামিং এর মধ্যে একটি অত্যন্ত গুরুত্বপূর্ণ কনসেপ্ট, যা আপনাকে একটি টাইপের সমস্ত প্রপার্টি বা ফিল্ডের উপর ভিত্তি করে একটি নতুন টাইপ তৈরি করতে দেয়।
ম্যাপড টাইপ ব্যবহার করার মাধ্যমে আপনি টাইপের একটি প্যাটার্ন বা ফর্ম্যাট অটোমেটিকভাবে পরিবর্তন করতে পারেন, যা কোডের পুনঃব্যবহারযোগ্যতা ও দক্ষতা বৃদ্ধি করে।
১. Mapped Types এর বেসিক সিনট্যাক্স
Mapped Types তৈরি করার জন্য সাধারণত keyof এবং in কিওয়ার্ড ব্যবহার করা হয়। keyof কিওয়ার্ড টাইপের সমস্ত প্রপার্টির নাম বের করে এবং in কিওয়ার্ডের মাধ্যমে সেই প্রপার্টি নামের উপর অপারেশন করা হয়।
উদাহরণ:
type Person = {
name: string;
age: number;
isActive: boolean;
};
// Mapped Type তৈরি করা
type ReadOnlyPerson = {
readonly [K in keyof Person]: Person[K];
};
const person: ReadOnlyPerson = {
name: "John",
age: 30,
isActive: true
};
// person.name = "Alice"; // Error: Cannot assign to 'name' because it is a read-only property.
এখানে:
keyof Personটাইপটিname,age,isActiveপ্রপার্টি গুলোকে বের করে।[K in keyof Person]এর মাধ্যমে সেই প্রপার্টিগুলির উপর অ্যাক্সেস পেতে পারি।readonlyকীওয়ার্ড ব্যবহার করে প্রপার্টিগুলিকে রিড-অনলি (immutable) করা হয়েছে, অর্থাৎ এর মান পরিবর্তন করা যাবে না।
২. Mapped Types ব্যবহার করে Conditional Transformation
Mapped Types ব্যবহার করে আপনি একটি টাইপের প্রপার্টির মান পরিবর্তন করতে পারেন শর্তসাপেক্ষভাবে, যেমন string থেকে number তে পরিবর্তন করা বা তার বিপরীত।
উদাহরণ:
type Person = {
name: string;
age: number;
isActive: boolean;
};
type PersonWithStringValues = {
[K in keyof Person]: string; // সব প্রপার্টির মান string হবে
};
const person: PersonWithStringValues = {
name: "Alice",
age: "30", // এখন এটি string টাইপ হবে
isActive: "true" // এটি string হবে, boolean নয়
};
এখানে:
PersonWithStringValuesMapped Type এর মাধ্যমে, সমস্ত প্রপার্টির মানstringহিসেবে পরিবর্তন করা হয়েছে।
৩. Mapped Types with as and infer
আপনি as এবং infer কিওয়ার্ডও ব্যবহার করতে পারেন Mapped Types এর সাথে কিছু কাস্টম টাইপ তৈরি করতে।
উদাহরণ (Transforming values of specific types):
type Person = {
name: string;
age: number;
isActive: boolean;
};
type TransformedPerson = {
[K in keyof Person]: Person[K] extends boolean ? string : Person[K];
};
const transformedPerson: TransformedPerson = {
name: "Alice",
age: 25,
isActive: "true", // isActive now accepts a string instead of a boolean
};
এখানে:
Person[K] extends boolean ? string : Person[K]দ্বারা, শুধুbooleanটাইপ প্রপার্টির মানকেstringএ রূপান্তর করা হয়েছে।isActiveএর টাইপstringহয়ে গেছে, কিন্তুnameএবংageপ্রপার্টিগুলির মান অপরিবর্তিত রয়েছে।
৪. Partial এবং Required Mapped Types
TypeScript এ কিছু বিল্ট-ইন Mapped Types রয়েছে, যেমন Partial এবং Required, যেগুলি TypeScript এর সাথে আসা যায়।
Partial<T>: এটি একটি টাইপের সমস্ত প্রপার্টিকে ঐচ্ছিক (optional) বানিয়ে দেয়।Required<T>: এটি একটি টাইপের সমস্ত প্রপার্টিকে আবশ্যক (required) বানিয়ে দেয়।
উদাহরণ:
type Person = {
name: string;
age: number;
isActive: boolean;
};
// Partial type: সব প্রপার্টি ঐচ্ছিক হয়ে যাবে
type PartialPerson = Partial<Person>;
const partialPerson: PartialPerson = {
name: "Alice", // age এবং isActive optional
};
// Required type: সব প্রপার্টি আবশ্যক হবে
type RequiredPerson = Required<Person>;
const requiredPerson: RequiredPerson = {
name: "John",
age: 30,
isActive: true, // এখানে সব প্রপার্টি আবশ্যক
};
এখানে:
PartialPersonএ সমস্ত প্রপার্টি ঐচ্ছিক হয়েছে, তাই আপনি শুধুnameপ্রদান করতে পারেন।RequiredPersonএ সমস্ত প্রপার্টি আবশ্যক হয়েছে, তাই আপনাকে অবশ্যই সব প্রপার্টি প্রদান করতে হবে।
৫. Mapped Types with in এবং keyof
keyof এবং in এর সংমিশ্রণ আপনাকে আরও জটিল Mapped Types তৈরি করতে সাহায্য করে। আপনি এটি ব্যবহার করে সমস্ত প্রপার্টি নাম বা ভ্যালু চেইন করতে পারেন।
উদাহরণ:
type Person = {
name: string;
age: number;
isActive: boolean;
};
type Nullable<T> = {
[K in keyof T]: T[K] | null; // সব প্রপার্টির মান null সহ গ্রহণ করবে
};
type NullablePerson = Nullable<Person>;
const nullablePerson: NullablePerson = {
name: null, // name এখন null হতে পারে
age: 25,
isActive: null, // isActive এখন null হতে পারে
};
এখানে:
Nullable<T>Mapped Type তৈরি করছে যা সব প্রপার্টির টাইপকেnullসহ গ্রহণ করতে সক্ষম।
সারাংশ
TypeScript এর Mapped Types আপনাকে একটি টাইপের প্রতিটি প্রপার্টি বা ফিল্ডের উপর ভিত্তি করে নতুন টাইপ তৈরি করতে সাহায্য করে। এটি আপনাকে টাইপের চেহারা পরিবর্তন করতে, প্রপার্টির মান পরিবর্তন করতে বা সব প্রপার্টি ঐচ্ছিক বা আবশ্যক করতে সক্ষম করে। Mapped Types এর ব্যবহার কৌশলগুলো টাইপ নিরাপত্তা নিশ্চিত করতে সাহায্য করে এবং কোডকে আরও পুনঃব্যবহারযোগ্য ও স্থিতিশীল করে তোলে।
Template Literal Types TypeScript-এর একটি শক্তিশালী ফিচার, যা স্ট্রিং টাইপের কাস্টম প্যাটার্ন তৈরি করতে সাহায্য করে। এটি আপনাকে স্ট্রিং টাইপগুলিকে একত্রিত করতে এবং কাস্টম স্ট্রিং টাইপ প্যাটার্ন তৈরি করতে সক্ষম করে। এই ফিচারটি template literals (স্ট্রিং টেমপ্লেট) এর মতো ব্যবহার হয়, কিন্তু টাইপ সিস্টেমে স্ট্রিং প্যাটার্নের ডাইনামিক টাইপগুলোকে রিপ্রেজেন্ট করতে।
১. Template Literal Types কী?
Template Literal Types ব্যবহার করে আপনি এক বা একাধিক স্ট্রিং টাইপের সমন্বয়ে নতুন স্ট্রিং টাইপ তৈরি করতে পারেন। এটি স্ট্রিং টেমপ্লেট লিটারাল কনসেপ্টের মতো কাজ করে, যেখানে আপনি ${} সিঙ্ক্স ব্যবহার করে টাইপ প্যারামিটার যোগ করতে পারেন।
এটি TypeScript 4.1 ভার্সন থেকে যুক্ত করা হয়েছে এবং এর মাধ্যমে আপনি ডাইনামিক স্ট্রিং টাইপ তৈরি করতে পারবেন, যা অনেক ক্ষেত্রে কোডকে আরও শক্তিশালী ও টাইপ সেফ করে।
২. Template Literal Types এর Sintax
Template Literal Types তৈরি করতে, স্ট্রিং টেমপ্লেটের মতো ${} সিঙ্ক্স ব্যবহার করা হয়। এখানে টাইপ প্যারামিটার হিসেবে স্ট্রিং বা অন্যান্য টাইপও ব্যবহার করা যেতে পারে।
উদাহরণ:
type Greeting = `Hello, ${string}!`;
const greetUser: Greeting = "Hello, John!"; // Valid
const greetAdmin: Greeting = "Hello, Admin!"; // Valid
const greetError: Greeting = "Hello, 123!"; // Valid
const greetInvalid: Greeting = "Hi, John!"; // Error: 'Hi' is not assignable to 'Hello, ${string}!'
এখানে, Greeting টাইপটি একটি স্ট্রিং টাইপ যেটি Hello, দিয়ে শুরু হবে এবং এরপর একটি string টাইপের মান থাকবে। "Hello, John!" এবং "Hello, Admin!" টাইপ হিসেবে গ্রহণযোগ্য, কিন্তু "Hi, John!" গ্রহণযোগ্য নয় কারণ এটি Hello, এর সাথে মিলে না।
৩. Template Literal Types এবং Union Types
Template Literal Types ইউজ করে আপনি Union Types (যেমন একাধিক স্ট্রিং প্যাটার্ন) তৈরি করতে পারেন। এর মাধ্যমে আপনি একাধিক স্ট্রিং প্যাটার্ন তৈরি করে বিভিন্ন ভ্যালিড স্ট্রিং টাইপ প্রযোজ্য করতে পারবেন।
উদাহরণ:
type Status = "success" | "error";
type Message = `Operation was a ${Status}`;
const successMessage: Message = "Operation was a success"; // Valid
const errorMessage: Message = "Operation was a error"; // Valid
const invalidMessage: Message = "Operation was a failed"; // Error: 'failed' is not assignable to 'success' | 'error'
এখানে, Status টাইপ success বা error হতে পারে এবং Message টাইপ Operation was a ${Status} হিসেবে গঠিত, অর্থাৎ এটি success বা error এর সাথে মিলে এমন স্ট্রিং হবে।
৪. Template Literal Types এবং Typed Parameters
আপনি Template Literal Types এর সাথে টাইপ প্যারামিটার ব্যবহার করতে পারেন, যাতে ডাইনামিকভাবে নতুন স্ট্রিং টাইপ তৈরি করা যায়।
উদাহরণ:
type OrderStatus = "pending" | "shipped" | "delivered";
type OrderMessage<T extends OrderStatus> = `Your order is ${T}`;
const message1: OrderMessage<"pending"> = "Your order is pending"; // Valid
const message2: OrderMessage<"shipped"> = "Your order is shipped"; // Valid
const message3: OrderMessage<"delivered"> = "Your order is delivered"; // Valid
const message4: OrderMessage<"cancelled"> = "Your order is cancelled"; // Error: 'cancelled' is not assignable to 'pending' | 'shipped' | 'delivered'
এখানে, OrderMessage টাইপটি একটি জেনেরিক টাইপ যেটি OrderStatus এর একটি মানকে টাইপ প্যারামিটার হিসেবে গ্রহণ করে এবং একটি স্ট্রিং তৈরি করে। এটি pending, shipped, বা delivered এর সঙ্গে মিলে এমন স্ট্রিং রিটার্ন করবে, কিন্তু cancelled হবে না।
৫. Template Literal Types এবং Type Composition
এছাড়া, আপনি একাধিক Template Literal Types একত্রিত (compose) করে আরও জটিল টাইপ তৈরি করতে পারেন।
উদাহরণ:
type VehicleType = "car" | "truck";
type FuelType = "petrol" | "diesel";
type VehicleInfo = `${VehicleType} - ${FuelType}`;
const vehicle1: VehicleInfo = "car - petrol"; // Valid
const vehicle2: VehicleInfo = "truck - diesel"; // Valid
const vehicle3: VehicleInfo = "car - electric"; // Error: 'electric' is not assignable to 'petrol' | 'diesel'
এখানে VehicleInfo একটি নতুন টাইপ যা VehicleType এবং FuelType টাইপগুলো একত্রিত করে। এটি কেবলমাত্র নির্দিষ্ট মিলে যাওয়া স্ট্রিং গ্রহণ করবে, যেমন "car - petrol" অথবা "truck - diesel"।
৬. ব্যবহারের সুবিধা
- ডাইনামিক টাইপ তৈরি: Template Literal Types দিয়ে আপনি কাস্টম স্ট্রিং প্যাটার্ন তৈরি করতে পারবেন।
- টাইপ সেফটি: এটি টাইপ সেফটি নিশ্চিত করতে সাহায্য করে, কারণ কম্পাইলার টাইপ চেকিং করবে এবং অবৈধ স্ট্রিং প্যাটার্নের ক্ষেত্রে ত্রুটি দেখাবে।
- কোডের পুনঃব্যবহারযোগ্যতা: একাধিক স্ট্রিং প্যাটার্নের সমন্বয় করতে এবং একই কনসেপ্ট বিভিন্ন জায়গায় ব্যবহার করতে পারবেন।
সারাংশ
Template Literal Types TypeScript-এ স্ট্রিং টাইপের সুনির্দিষ্ট প্যাটার্ন তৈরি করার একটি শক্তিশালী পদ্ধতি। এটি টাইপের উপর নির্ভরশীল কোড তৈরি করতে সাহায্য করে, যেমন একটি নির্দিষ্ট স্ট্রিং টাইপের প্যাটার্ন তৈরি করা যা কেবল নির্দিষ্ট মান বা কনসট্রেইন্টে কাজ করবে। এর মাধ্যমে টাইপ সেফটি নিশ্চিত করা যায় এবং কোডের রিডেবিলিটি ও মেইনটেনেবিলিটি বৃদ্ধি পায়।
Read more