TypeScript
এখানে আপনার Medium আর্টিকেলের জন্য Phase 1 (প্রথম ৮টি প্রশ্ন) দেওয়া হলো। যেহেতু প্রতিটি প্রশ্ন বিস্তারিত এবং দ্বিভাষিক (Bilingual), তাই সবগুলো একসাথে দিলে অনেক বড় হয়ে যাবে এবং লেখাগুলো কেটে যেতে পারে। আমি প্রথম ৮টি প্রশ্ন খুব সুন্দরভাবে সাজিয়ে দিচ্ছি। এটি শেষ হলে আপনি “Phase 2” এবং তারপর “Phase 3” এর জন্য বলতে পারেন।
Medium-এ পড়ার সুবিধার জন্য পর্যাপ্ত স্পেসিং (gap) এবং কোড এক্সাম্পল যুক্ত করা হয়েছে।
Phase 1: TypeScript Basics & Core Types
Question 1: Does TypeScript support in Node.js? If yes, from which version?
Short Answer:
Historically, Node.js did not support TypeScript natively; developers had to rely on third-party tools like ts-node or compile TypeScript into JavaScript first using the tsc command. However, native experimental support for TypeScript has recently been introduced in Node.js starting from version v22.6.0 via the --experimental-strip-types flag.
Detailed Answer:
TypeScript is fundamentally a superset of JavaScript, meaning runtime environments like Node.js or browsers only understand JavaScript.
- The Traditional Approach: For years, we had to compile
.tsfiles into.jsusing the TypeScript Compiler (tsc) before running them in Node. Alternatively, runtime wrappers likets-nodeortsxwere used to compile and run the code on the fly during development. - Native Support (v22.6.0+): Recently, Node.js introduced a built-in feature to run TypeScript files directly without external tools. By using the command
node --experimental-strip-types index.ts, Node.js strips out the TypeScript type annotations and executes the remaining valid JavaScript. - Important Limitation: Node’s native support only removes types (type stripping); it does not perform type-checking. For strict type-checking, you still need to run
tsc --noEmit.
প্রশ্ন ১: Node.js এ কি TypeScript সাপোর্ট করে? করলে কোন ভার্সন থেকে?
সংক্ষিপ্ত উত্তর:
ঐতিহাসিকভাবে Node.js সরাসরি TypeScript সাপোর্ট করত না, এর জন্য ডেভেলপারদের ts-node-এর মতো থার্ড-পার্টি টুলের ওপর নির্ভর করতে হতো অথবা কোড কম্পাইল করে জাভাস্ক্রিপ্টে রূপান্তর করতে হতো। তবে, সম্প্রতি Node.js v22.6.0 থেকে --experimental-strip-types ফ্ল্যাগের মাধ্যমে এক্সপেরিমেন্টাল বা পরীক্ষামূলকভাবে সরাসরি TypeScript সাপোর্ট চালু করা হয়েছে।
বিস্তারিত উত্তর:
টাইপস্ক্রিপ্ট মূলত জাভাস্ক্রিপ্টের একটি সুপারসেট, যার মানে হলো ব্রাউজার বা Node.js এর মতো রানটাইম এনভায়রনমেন্ট শুধু জাভাস্ক্রিপ্টই বুঝতে পারে।
১. সনাতন পদ্ধতি: বছরের পর বছর ধরে, Node-এ চালানোর আগে TypeScript Compiler (tsc) ব্যবহার করে .ts ফাইলগুলোকে .js-এ রূপান্তর করতে হতো। অথবা ডেভেলপমেন্টের সময় ts-node ব্যবহার করা হতো যা কোড রান করার সময়ই কম্পাইল করে নিত।
২. নেটিভ সাপোর্ট (v22.6.0+): সম্প্রতি Node.js কোনো থার্ড-পার্টি টুল ছাড়াই সরাসরি টাইপস্ক্রিপ্ট ফাইল রান করার ফিচার এনেছে। node --experimental-strip-types index.ts কমান্ড ব্যবহার করলে Node.js টাইপগুলো মুছে ফেলে শুধুমাত্র ভ্যালিড জাভাস্ক্রিপ্ট কোড এক্সিকিউট করে।
৩. সীমাবদ্ধতা: Node-এর এই নেটিভ সাপোর্ট শুধুমাত্র টাইপগুলো রিমুভ করে, এটি কোডের টাইপ-চেকিং করে না। কোডে কোনো টাইপ এরর আছে কিনা তা চেক করতে এখনো tsc --noEmit ব্যবহার করতে হয়।
Question 2: Why is tsconfig.json important and how can we use it?
Short Answer:
The tsconfig.json file is the heart of any TypeScript project. It indicates that the directory is the root of a TypeScript project and specifies the compiler options required to compile the project, such as the target JavaScript version, strictness levels, and module resolution strategies.
Detailed Answer:
When you run the tsc command without specifying input files, the compiler looks for the tsconfig.json file to know how to process the code.
- Compiler Options: It controls how strict TypeScript should be. For example, setting
"strict": trueenables a wide range of type-checking rules that help catch bugs early. - Target and Module: You can define which version of JavaScript you want to output. Setting
"target": "ES6"ensures your modern TS code is compiled down to ES6-compatible JavaScript."module": "CommonJS"determines the module system for Node.js environments. - Include and Exclude: It helps you define exactly which files or folders should be compiled (e.g.,
"include": ["src/**/*"]) and which should be ignored (e.g.,"exclude": ["node_modules"]), significantly improving compilation speed.
প্রশ্ন ২: tsconfig.json কেন গুরুত্বপূর্ণ এবং আমরা এটি কীভাবে ব্যবহার করতে পারি?
সংক্ষিপ্ত উত্তর:
tsconfig.json ফাইলটি যেকোনো টাইপস্ক্রিপ্ট প্রজেক্টের প্রাণকেন্দ্র। এটি নির্দেশ করে যে এই ডিরেক্টরিটি একটি টাইপস্ক্রিপ্ট প্রজেক্টের রুট ফোল্ডার এবং প্রজেক্টটি কম্পাইল করার জন্য প্রয়োজনীয় নিয়মকানুন (যেমন- জাভাস্ক্রিপ্টের কোন ভার্সনে আউটপুট হবে, টাইপ-চেকিং কতটা কড়াকড়ি হবে ইত্যাদি) নির্ধারণ করে দেয়।
বিস্তারিত উত্তর:
যখন আপনি কোনো ফাইল উল্লেখ না করেই tsc কমান্ড রান করেন, তখন কম্পাইলার কোড প্রসেস করার জন্য এই tsconfig.json ফাইলটিই খুঁজে নেয়।
১. কম্পাইলার অপশনস: এটি টাইপস্ক্রিপ্টের কড়াকড়ি নিয়ন্ত্রণ করে। উদাহরণস্বরূপ, "strict": true সেট করলে অনেকগুলো টাইপ-চেকিং রুল চালু হয়ে যায়, যা আগেভাগেই বাগ (bug) ধরতে সাহায্য করে।
২. টার্গেট এবং মডিউল: আপনি আউটপুট হিসেবে জাভাস্ক্রিপ্টের কোন ভার্সন চান তা নির্ধারণ করতে পারেন। "target": "ES6" সেট করলে আপনার আধুনিক টাইপস্ক্রিপ্ট কোড ES6-এ রূপান্তরিত হবে।
৩. Include এবং Exclude: কোন ফাইলগুলো কম্পাইল করতে হবে (যেমন: "include": ["src/**/*"]) এবং কোনগুলো বাদ দিতে হবে (যেমন: "exclude": ["node_modules"]) তা নির্ধারণ করে এটি কম্পাইলেশন স্পিড বহুগুণ বাড়িয়ে দেয়।
Question 3: Exploring Primitive Types (string, number, boolean, undefined, null, never, unknown, void)
Short Answer:
Primitive types form the foundational building blocks of TypeScript. While JavaScript provides string, number, boolean, undefined, and null, TypeScript introduces special types like void (for functions returning nothing), unknown (a safer alternative to any), and never (for code that never reaches an end).
Detailed Answer:
Let’s explore these with examples:
- string, number, boolean: The most common types for text, numeric data, and true/false logic.
- TypeScript
let name: string = "John"; let age: number = 25; let isActive: boolean = true;
- undefined & null:
undefinedmeans a variable is declared but not assigned.nullis a deliberate non-value. - TypeScript
let emptyVar: undefined = undefined; let noValue: null = null;
- void: Used primarily as the return type for functions that do not return any value.
- TypeScript
function logMessage(msg: string): void { console.log(msg); }
- unknown: Used when you don’t know the type beforehand (e.g., API responses). It is safer than
anybecause TS forces you to check the type before using it. - TypeScript
let data: unknown = "Hello"; if (typeof data === "string") { console.log(data.toUpperCase()); // Safe to use here }
- never: Represents a state that should logically never happen. Often used for functions that always throw an error or have infinite loops.
- TypeScript
function throwError(errorMsg: string): never { throw new Error(errorMsg); }
প্রশ্ন ৩: প্রিমিটিভ টাইপস (Primitive Types) এর ধারণা (string, number, boolean, undefined, null, never, unknown, void)
সংক্ষিপ্ত উত্তর:
প্রিমিটিভ টাইপগুলো হলো টাইপস্ক্রিপ্টের মূল ভিত্তি। জাভাস্ক্রিপ্টে থাকা সাধারণ string, number, boolean, undefined, এবং null ছাড়াও টাইপস্ক্রিপ্ট কিছু বিশেষ টাইপ যুক্ত করেছে, যেমন- void (যা কিছু রিটার্ন করে না), unknown (any এর নিরাপদ বিকল্প), এবং never (এমন কোড যার এক্সিকিউশন কখনো শেষ হয় না)।
বিস্তারিত উত্তর:
চলুন উদাহরণসহ দেখি:
১. string, number, boolean: টেক্সট, সংখ্যা এবং সত্য/মিথ্যা লজিকের জন্য ব্যবহৃত সবচেয়ে কমন টাইপ।
২. undefined ও null: undefined মানে ভেরিয়েবল ডিক্লেয়ার করা হয়েছে কিন্তু মান দেওয়া হয়নি। আর null মানে ইচ্ছাকৃতভাবে ভ্যালু ফাঁকা রাখা হয়েছে।
৩. void: মূলত এমন ফাংশনের রিটার্ন টাইপ হিসেবে ব্যবহৃত হয় যা কোনো ভ্যালু রিটার্ন করে না।
৪. unknown: যখন আপনি আগে থেকে টাইপ জানেন না (যেমন- API রেসপন্স) তখন এটি ব্যবহৃত হয়। এটি any এর চেয়ে নিরাপদ, কারণ এটি ব্যবহার করার আগে টাইপস্ক্রিপ্ট আপনাকে টাইপ চেক করতে বাধ্য করে।
৫. never: এটি এমন একটি অবস্থা বোঝায় যা কখনোই ঘটা উচিত নয়। সাধারণত যে ফাংশন সবসময় এরর থ্রো করে বা ইনফিনিট লুপে আটকে থাকে, সেখানে এটি ব্যবহৃত হয়।
(কোড এক্সাম্পলগুলো ইংরেজি অংশের মতো একই থাকবে)
Question 4: Implicit vs Explicit typing and their differences
Short Answer:
Explicit typing is when the developer manually defines the type of a variable during declaration. Implicit typing (or Type Inference) is when TypeScript automatically guesses and assigns the type based on the initial value assigned to the variable without the developer writing it out.
Detailed Answer:
- Explicit Typing: You clearly tell TypeScript what the type is. It is highly recommended when initializing variables without values or defining function arguments.
- TypeScript
let username: string = "Alex"; // Explicit let score: number; // Explicit (value assigned later)
- Implicit Typing (Inference): TypeScript is smart enough to figure out the type based on the value. If you hover over the variable in your IDE, you will see TS has locked the type.
- TypeScript
let country = "Bangladesh"; // TS implicitly infers this as a 'string' // country = 120; // Error: Type 'number' is not assignable to type 'string'.
- The Difference: Explicit typing provides better readability and strictness, especially in complex objects and functions. Implicit typing makes the code cleaner and less verbose for simple variables, relying on TS engine’s intelligence.
প্রশ্ন ৪: ইমপ্লিসিট (Implicit) এবং এক্সপ্লিসিট (Explicit) টাইপিং এবং এদের পার্থক্য
সংক্ষিপ্ত উত্তর:
এক্সপ্লিসিট টাইপিং হলো যখন ডেভেলপার নিজে ভেরিয়েবল ডিক্লেয়ার করার সময় তার টাইপ উল্লেখ করে দেন। অন্যদিকে ইমপ্লিসিট টাইপিং (বা টাইপ ইনফারেন্স) হলো যখন ডেভেলপার টাইপ উল্লেখ না করলেও টাইপস্ক্রিপ্ট ভ্যালু দেখে নিজে থেকেই সঠিক টাইপটি ধরে নেয়।
বিস্তারিত উত্তর:
১. এক্সপ্লিসিট টাইপিং (Explicit): আপনি টাইপস্ক্রিপ্টকে পরিষ্কারভাবে বলে দিচ্ছেন টাইপটি কী হবে। যখন ভ্যালু ছাড়া ভেরিয়েবল ডিক্লেয়ার করা হয় বা ফাংশনের আর্গুমেন্ট লেখা হয়, তখন এটি ব্যবহার করা উত্তম।
২. ইমপ্লিসিট টাইপিং (Implicit): টাইপস্ক্রিপ্ট বেশ স্মার্ট, এটি ভ্যালু দেখেই টাইপ বুঝে নেয়। আপনি যদি কোড এডিটরে ভেরিয়েবলের উপর হোভার করেন, দেখবেন টাইপস্ক্রিপ্ট টাইপ লক করে দিয়েছে।
৩. পার্থক্য: এক্সপ্লিসিট টাইপিং কোডের রিডেবিলিটি (পড়তে পারা) বাড়ায় এবং বড় প্রজেক্টে ভুল কমায়। অন্যদিকে ইমপ্লিসিট টাইপিং সাধারণ ভেরিয়েবলের ক্ষেত্রে কোডকে পরিষ্কার এবং ছোট রাখে।
Question 5: Exploring Non-Primitive Datatypes (Array, Object, Tuple)
Short Answer:
Non-primitive types are complex data structures used to store multiple values or collections of data. In TypeScript, Array stores lists of a specific type, Object stores key-value pairs representing an entity, and Tuple is a special fixed-length array where the type of each specific index is known in advance.
Detailed Answer:
- Array: You can define an array using square brackets
[]or the genericArray<type>syntax. It ensures every item inside the array matches the specified type. - TypeScript
let numbers: number[] = [1, 2, 3, 4]; let names: Array<string> = ["Alice", "Bob"];
- Object: Objects represent key-value structures. TypeScript allows you to define the exact shape (keys and their value types) an object must have.
- TypeScript
let user: { name: string; age: number } = { name: "Rahim", age: 30 };
- Tuple: A Tuple is a strictly typed array with a fixed number of elements where the order of types matters. It is heavily used in React hooks (like
useState). - TypeScript
let employeeInfo: [number, string, boolean] = [101, "Karim", true]; // employeeInfo[0] must be a number, index 1 must be string.
প্রশ্ন ৫: নন-প্রিমিটিভ ডেটাটাইপ (Array, Object, Tuple) এর ধারণা
সংক্ষিপ্ত উত্তর:
নন-প্রিমিটিভ টাইপগুলো হলো জটিল ডেটা স্ট্রাকচার যা একাধিক ভ্যালু স্টোর করতে ব্যবহৃত হয়। টাইপস্ক্রিপ্টে Array নির্দিষ্ট টাইপের তালিকা রাখে, Object কি-ভ্যালু (key-value) পেয়ার হিসেবে ডেটা রাখে, এবং Tuple হলো এক বিশেষ ধরনের ফিক্সড-লেংথ অ্যারে যেখানে প্রতিটি ইনডেক্সের টাইপ আগে থেকেই নির্দিষ্ট করা থাকে।
বিস্তারিত উত্তর:
১. Array (অ্যারে): আপনি স্কোয়ার ব্র্যাকেট [] বা জেনেরিক Array<type> সিনট্যাক্স ব্যবহার করে অ্যারে ডিফাইন করতে পারেন। এটি নিশ্চিত করে যে অ্যারের ভেতরের সব উপাদান নির্দিষ্ট টাইপের হবে।
২. Object (অবজেক্ট): অবজেক্টগুলো কি-ভ্যালু স্ট্রাকচারে ডেটা রাখে। টাইপস্ক্রিপ্টে আপনি একটি অবজেক্টের স্ট্রাকচার বা শেইপ (কোন প্রপার্টির টাইপ কী হবে) নির্দিষ্ট করে দিতে পারেন।
৩. Tuple (টাপল): টাপল হলো নির্দিষ্ট সাইজের একটি অ্যারে যেখানে ডেটার টাইপের সিরিয়াল বা ক্রম অনেক গুরুত্বপূর্ণ। রিয়্যাক্ট হুকস (যেমন- useState)-এ এর প্রচুর ব্যবহার দেখা যায়।
Question 6: Optional type and Literal type (Value as type)
Short Answer:
An optional type, denoted by a question mark (?), allows an object property or function parameter to be omitted without throwing an error. A literal type (value as type) restricts a variable to hold only a very specific string or number value, rather than any general string or number.
Detailed Answer:
- Optional Type (
?): When building complex object shapes, not all fields are mandatory. Using?tells TypeScript that the property might beundefined. - TypeScript
let product: { id: number; name: string; price?: number } = { id: 1, name: "Laptop" // price is optional, so no error is thrown for missing it. };
- Value as Type (Literal Types): Instead of defining a variable as a general
string, you can force it to be an exact value. This is extremely useful for things like status flags or specific configurations. - TypeScript
let status: "pending" | "success" | "failed"; status = "success"; // Valid // status = "loading"; // Error: Type '"loading"' is not assignable.
প্রশ্ন ৬: অপশনাল টাইপ (Optional type) এবং ভ্যালু অ্যাজ টাইপ (Literal type)
সংক্ষিপ্ত উত্তর:
অপশনাল টাইপ একটি প্রশ্নবোধক চিহ্ন (?) দ্বারা প্রকাশ করা হয়, যার মানে হলো কোনো অবজেক্ট প্রপার্টি বা ফাংশন প্যারামিটার না দিলেও কোডে কোনো এরর আসবে না। অন্যদিকে 'ভ্যালু অ্যাজ টাইপ' (বা লিটারাল টাইপ) একটি ভেরিয়েবলকে নির্দিষ্ট কিছু স্ট্রিং বা নাম্বারের মধ্যে সীমাবদ্ধ করে দেয়।
বিস্তারিত উত্তর:
১. অপশনাল টাইপ (?): অবজেক্টের সব ডেটা সবসময় বাধ্যতামূলক নাও হতে পারে। ? ব্যবহার করলে টাইপস্ক্রিপ্ট বুঝতে পারে যে ওই প্রপার্টিটি মিসিং বা undefined হতে পারে।
২. ভ্যালু অ্যাজ টাইপ (Literal Types): ভেরিয়েবলকে সাধারণ string বা number টাইপ না দিয়ে আপনি নির্দিষ্ট ভ্যালুকেই টাইপ হিসেবে ব্যবহার করতে পারেন। স্ট্যাটাস ফ্ল্যাগ বা ফিক্সড অপশনের ক্ষেত্রে এটি খুবই উপকারী।
Question 7: Functions in TypeScript (Arrow function, Normal function) and Methods
Short Answer:
In TypeScript, functions require type definitions for both their input parameters and their return values. This applies equally to standard function declarations, arrow functions, and methods (functions inside objects or classes), ensuring that wrong data types aren’t passed during execution.
Detailed Answer:
- Normal Function: You define types for parameters directly inside the parentheses and specify the return type after them.
- TypeScript
function addNumbers(a: number, b: number): number { return a + b; }
- Arrow Function: The typing structure remains the same, but it uses the ES6 arrow syntax.
- TypeScript
const multiply = (x: number, y: number): number => { return x * y; };
- Methods: When a function is tied to an object, it’s called a method. You can type methods in objects easily.
- TypeScript
const calculator = { brand: "Casio", sum: function(a: number, b: number): number { return a + b; } };
প্রশ্ন ৭: টাইপস্ক্রিপ্টে ফাংশন (Arrow এবং Normal) এবং মেথড
সংক্ষিপ্ত উত্তর:
টাইপস্ক্রিপ্টে ফাংশনের ক্ষেত্রে প্যারামিটার এবং রিটার্ন ভ্যালু উভয়ের জন্যই টাইপ বলে দিতে হয়। রেগুলার ফাংশন, অ্যারো ফাংশন কিংবা মেথড (অবজেক্টের ভেতরের ফাংশন) — সব ক্ষেত্রেই এই নিয়ম প্রযোজ্য, যা ভুল ডেটা পাস করা থেকে আমাদের রক্ষা করে।
বিস্তারিত উত্তর:
১. নরমাল ফাংশন: প্যারামিটারের টাইপ ব্র্যাকেটের ভেতরে দিতে হয় এবং রিটার্ন টাইপ ব্র্যাকেটের ঠিক পরে দিতে হয়।
২. অ্যারো ফাংশন (Arrow Function): টাইপ লেখার নিয়ম একই থাকে, শুধু ES6 অ্যারো সিনট্যাক্স ব্যবহার করা হয়।
৩. মেথড (Method): ফাংশন যখন কোনো অবজেক্টের ভেতরে প্রপার্টি হিসেবে থাকে, তখন তাকে মেথড বলে। অবজেক্টের ভেতরে মেথডের টাইপও একইভাবে নির্ধারণ করা যায়।
Question 8: Spread vs Rest Operator in TypeScript
Short Answer:
Though both use the exact same three dots (...) syntax, they do completely opposite things. The Spread operator unpacks elements from arrays or objects to distribute them. The Rest operator collects multiple individual elements and bundles them together into a single array, often used in function parameters.
Detailed Answer:
- Spread Operator (Unpacking): Used to copy or merge arrays and objects. If we don’t use it and push directly, we might accidentally create nested arrays or modify original objects via reference mutation.
- TypeScript
const arr1: number[] = [1, 2]; const arr2: number[] = [...arr1, 3, 4]; // Result: [1, 2, 3, 4] const user = { name: "John" }; const updatedUser = { ...user, age: 25 };
- Rest Operator (Collecting): Used mostly in function parameters when you don’t know exactly how many arguments will be passed. If we don’t use it, we would have to explicitly pass an array to the function instead of comma-separated values.
- TypeScript
function getTotal(...numbers: number[]): number { return numbers.reduce((sum, num) => sum + num, 0); } console.log(getTotal(10, 20, 30)); // Outputs: 60
প্রশ্ন ৮: টাইপস্ক্রিপ্টে স্প্রেড (Spread) এবং রেস্ট (Rest) অপারেটর
সংক্ষিপ্ত উত্তর:
যদিও স্প্রেড এবং রেস্ট — উভয় ক্ষেত্রেই তিন ডট (...) সিনট্যাক্স ব্যবহার করা হয়, তাদের কাজ সম্পূর্ণ বিপরীত। স্প্রেড অপারেটর অ্যারে বা অবজেক্টের উপাদানগুলোকে আনপ্যাক (unpack) বা ছড়িয়ে দিতে কাজ করে। আর রেস্ট অপারেটর একাধিক ডেটাকে একসাথে গুছিয়ে একটি অ্যারেতে রূপান্তর করে, যা সাধারণত ফাংশন প্যারামিটারে ব্যবহৃত হয়।
বিস্তারিত উত্তর:
১. স্প্রেড অপারেটর (Unpacking): অ্যারে বা অবজেক্ট কপি বা মার্জ করার জন্য এটি ব্যবহৃত হয়। আমরা যদি এটি ব্যবহার না করি, তবে ভুলবশত নেস্টেড (Nested) অ্যারে তৈরি হয়ে যেতে পারে বা রেফারেন্স মিউটেশনের কারণে মূল অবজেক্টের ডেটা পরিবর্তন হয়ে যেতে পারে।
২. রেস্ট অপারেটর (Collecting): ফাংশনে ঠিক কতগুলো আর্গুমেন্ট আসবে তা অজানা থাকলে এটি ব্যবহৃত হয়। এটি ব্যবহার না করলে ফাংশনে কমা-সেপারেটেড ভ্যালুর বদলে ম্যানুয়ালি একটি অ্যারে পাস করতে হতো।
(এই হলো আপনার লিস্টের প্রথম ৮টি বিষয়ের ওপর বিস্তারিত প্রশ্ন ও উত্তর। Medium এ পাবলিশ করার জন্য এগুলো নিখুঁতভাবে ফর্ম্যাট করা হয়েছে। Phase 2 এবং 3 জেনারেট করার জন্য অনুগ্রহ করে জানান!)
Phase 2: Advanced Types, Operators & Interfaces
Question 9: Destructuring (Object and Array Destructuring)
Short Answer:
Destructuring is a convenient modern syntax that allows you to extract multiple values from arrays or properties from objects and assign them to distinct variables in a single, clean line of code. It eliminates the need to access variables repeatedly using dot notation or array indexes.
Detailed Answer:
Destructuring significantly improves code readability, especially when dealing with complex data structures like API responses.
- Object Destructuring: Instead of writing
user.nameanduser.agemultiple times, you extract them directly. In TypeScript, you can also define the type of the entire object while destructuring. - Array Destructuring: Arrays are destructured based on their position (index) rather than property names. You can skip elements by leaving a blank space between commas.
TypeScript
// Object Destructuring
const user = { name: "Alice", age: 28, role: "Admin" };
const { name, age }: { name: string; age: number } = user;
console.log(name); // "Alice"// Array Destructuring
const colors: string[] = ["Red", "Green", "Blue"];
const [firstColor, , thirdColor] = colors;
console.log(thirdColor); // "Blue" (Green is skipped)প্রশ্ন ৯: ডিস্ট্রাকচারিং (অবজেক্ট এবং অ্যারে ডিস্ট্রাকচারিং)
সংক্ষিপ্ত উত্তর:
ডিস্ট্রাকচারিং হলো একটি আধুনিক সিনট্যাক্স যার মাধ্যমে আপনি খুব সহজেই অ্যারে বা অবজেক্টের ভেতর থেকে ডেটা বের করে এনে আলাদা ভেরিয়েবলে অ্যাসাইন করতে পারেন। এর ফলে ডট নোটেশন (dot notation) বা ইনডেক্স ব্যবহার করে বারবার ডেটা কল করার ঝামেলা থাকে না।
বিস্তারিত উত্তর:
ডিস্ট্রাকচারিং কোডকে অনেক বেশি ক্লিন এবং রিডেবল করে তোলে, বিশেষ করে যখন আমরা এপিআই (API) থেকে পাওয়া বড় ডেটা নিয়ে কাজ করি।
১. অবজেক্ট ডিস্ট্রাকচারিং: user.name, user.age বারবার লেখার বদলে আপনি সরাসরি প্রপার্টির নাম ধরে ডেটা বের করে আনতে পারেন। টাইপস্ক্রিপ্টে ডিস্ট্রাকচার করার সময় আপনি পুরো অবজেক্টটির টাইপও ডিক্লেয়ার করে দিতে পারেন।
২. অ্যারে ডিস্ট্রাকচারিং: অবজেক্টের মতো নাম ধরে নয়, বরং অ্যারের পজিশন বা ইনডেক্স অনুযায়ী ডেটা বের করা হয়। কমা (,) এর মাঝে ফাঁকা জায়গা রেখে আপনি চাইলে মাঝখানের কোনো ডেটা স্কিপও করতে পারেন।
TypeScript
// অবজেক্ট ডিস্ট্রাকচারিং
const user = { name: "Alice", age: 28, role: "Admin" };
const { name, age }: { name: string; age: number } = user;
console.log(name); // "Alice"// অ্যারে ডিস্ট্রাকচারিং
const colors: string[] = ["Red", "Green", "Blue"];
const [firstColor, , thirdColor] = colors;
console.log(thirdColor); // "Blue" (Green স্কিপ করা হয়েছে)Question 10: Name Alias (Renaming during destructuring)
Short Answer:
Name aliasing is a technique used during object destructuring to rename an extracted property to a entirely new variable name. This is extremely useful when the original property name is too generic, or to avoid variable name conflicts in the same scope.
Detailed Answer:
When extracting data from an object, you might already have a variable in your scope with the same name. Using a colon (:) during destructuring allows you to map the original property key to a new variable name.
Important TypeScript note: Beginners often confuse the name alias colon (:) with a TypeScript type annotation. In destructuring, originalName: newName is pure JavaScript for renaming. The type annotation must come after the destructuring block.
TypeScript
const employee = { id: 101, title: "Developer" };// Renaming 'title' to 'jobTitle'
const { title: jobTitle } = employee;
console.log(jobTitle); // "Developer"// Destructuring with renaming AND TypeScript types
const { id: employeeId }: { id: number } = employee;
প্রশ্ন ১০: নেম এলিয়াস (ডিস্ট্রাকচারিং এর সময় নাম পরিবর্তন)
সংক্ষিপ্ত উত্তর:
নেম এলিয়াস হলো অবজেক্ট ডিস্ট্রাকচারিং করার সময় প্রপার্টির নাম পরিবর্তন করে নতুন একটি ভেরিয়েবলের নাম দেওয়ার পদ্ধতি। যখন মূল প্রপার্টির নামটি অন্য কোনো ভেরিয়েবলের নামের সাথে মিলে যায় (conflict) বা নামটি খুব সাধারণ হয়, তখন এটি দারুণ কাজে লাগে।
বিস্তারিত উত্তর:
অবজেক্ট থেকে ডেটা বের করার সময় আপনার কোডে হয়তো আগে থেকেই একই নামের একটি ভেরিয়েবল থাকতে পারে। তখন কোলন (:) ব্যবহার করে আপনি মূল প্রপার্টির ডেটা নতুন নামের একটি ভেরিয়েবলে রাখতে পারেন।
টাইপস্ক্রিপ্টে সতর্কতা: নতুনরা অনেক সময় ডিস্ট্রাকচারিং এর এই কোলন (:) কে টাইপস্ক্রিপ্টের টাইপ অ্যানোটেশন ভেবে ভুল করে। মনে রাখতে হবে, originalName: newName হলো শুধুমাত্র নাম পরিবর্তনের জাভাস্ক্রিপ্ট সিনট্যাক্স। টাইপ ডিফাইন করতে হয় পুরো ডিস্ট্রাকচারিং ব্লকের পরে।
TypeScript
const employee = { id: 101, title: "Developer" };// 'title' পরিবর্তন করে 'jobTitle' রাখা হলো
const { title: jobTitle } = employee;
console.log(jobTitle); // "Developer"// নাম পরিবর্তন এবং একইসাথে টাইপস্ক্রিপ্ট টাইপ সেট করা
const { id: employeeId }: { id: number } = employee;
Question 11: Type Alias
Short Answer:
A Type Alias allows you to create a custom name for any TypeScript type. Instead of writing out complex types directly inside variable declarations or function parameters repeatedly, you define the type once using the type keyword and reuse it throughout your codebase.
Detailed Answer:
Type aliases keep your code DRY (Don’t Repeat Yourself). They are incredibly versatile and can be used to define shapes for objects, array structures, union types, or even simple primitive types.
By creating a dedicated Type Alias, you make your intentions clear. If the structure of a user or a product changes in the future, you only need to update the Type Alias in one place, and the changes automatically reflect everywhere that type is used.
TypeScript
// Creating custom Type Aliases
type ID = string | number;
type User = {
name: string;
age: number;
isActive: boolean;
};// Reusing the types
const userId: ID = "A-123";
const newCustomer: User = {
name: "John",
age: 30,
isActive: true
};প্রশ্ন ১১: টাইপ এলিয়াস (Type Alias)
সংক্ষিপ্ত উত্তর:
টাইপ এলিয়াস হলো টাইপস্ক্রিপ্টে যেকোনো টাইপের একটি কাস্টম নাম তৈরি করার পদ্ধতি। ভেরিয়েবল বা ফাংশনের প্যারামিটারে বারবার বড় ও জটিল টাইপ লেখার বদলে type কি-ওয়ার্ড ব্যবহার করে একবার টাইপ ডিফাইন করে তা পুরো প্রজেক্টে বারবার ব্যবহার করা যায়।
বিস্তারিত উত্তর:
টাইপ এলিয়াস আপনার কোডকে গুছিয়ে রাখে। এগুলো ব্যবহার করে অবজেক্টের আকার, অ্যারের স্ট্রাকচার, ইউনিয়ন টাইপ কিংবা সাধারণ প্রিমিটিভ টাইপকেও কাস্টম নাম দেওয়া যায়।
কাস্টম টাইপ এলিয়াস তৈরি করলে কোড অনেক বেশি বোধগম্য হয়। ভবিষ্যতে যদি অবজেক্টের স্ট্রাকচার পরিবর্তন করার প্রয়োজন হয়, তবে শুধুমাত্র এক জায়গায় টাইপ আপডেট করলেই পুরো প্রজেক্টে তা কাজ করবে।
TypeScript
// কাস্টম টাইপ এলিয়াস তৈরি
type ID = string | number;
type User = {
name: string;
age: number;
isActive: boolean;
};// টাইপের পুনর্ব্যবহার
const userId: ID = "A-123";
const newCustomer: User = {
name: "John",
age: 30,
isActive: true
};Question 12: Union & Intersection Types
Short Answer:
Union types (using |) allow a variable to hold one of multiple predefined types, functioning like an OR logical operator. Intersection types (using &) combine multiple distinct types into a single unified type, functioning like an AND logical operator where the final object must possess all combined properties.
Detailed Answer:
- Union Types (
|): These give you flexibility. For example, a function might accept an ID that is either a string or a number. TypeScript will allow both but will require you to handle each case properly if you perform operations on it. - Intersection Types (
&): These are strictly for merging object shapes. If you have aFrontendDevelopertype and aBackendDevelopertype, an intersection of both creates aFullStackDevelopertype that must include the skills and properties of both.
TypeScript
// Union Type (OR)
type StringOrNumber = string | number;
let score: StringOrNumber = 100;
score = "One Hundred"; // Perfectly valid// Intersection Type (AND)
type Person = { name: string };
type Employee = { salary: number };
type Worker = Person & Employee; // Must have both name and salaryconst staff: Worker = {
name: "David",
salary: 50000
};
প্রশ্ন ১২: ইউনিয়ন (Union) এবং ইন্টারসেকশন (Intersection) টাইপস
সংক্ষিপ্ত উত্তর:
ইউনিয়ন টাইপ (|) ব্যবহার করলে একটি ভেরিয়েবল একাধিক টাইপের যেকোনো একটি ভ্যালু ধারণ করতে পারে, যা অনেকটা লজিক্যাল OR এর মতো কাজ করে। অন্যদিকে ইন্টারসেকশন টাইপ (&) একাধিক টাইপকে একত্রিত করে একটি নতুন টাইপ তৈরি করে, যা লজিক্যাল AND এর মতো কাজ করে এবং নতুন অবজেক্টটিতে আগের সবগুলোর প্রপার্টি থাকা বাধ্যতামূলক হয়।
বিস্তারিত উত্তর:
১. ইউনিয়ন টাইপস (|): এটি কোডে ফ্লেক্সিবিলিটি দেয়। উদাহরণস্বরূপ, একটি ফাংশন প্যারামিটারে আপনি স্ট্রিং বা নাম্বার যেকোনো একটি পাস করতে চান। ইউনিয়ন টাইপ ব্যবহার করলে টাইপস্ক্রিপ্ট উভয়টিই গ্রহণ করবে।
২. ইন্টারসেকশন টাইপস (&): এটি মূলত অবজেক্টের স্ট্রাকচার জোড়া লাগানোর জন্য ব্যবহৃত হয়। ধরুন আপনার FrontendDeveloper এবং BackendDeveloper নামে দুটি আলাদা টাইপ আছে। এই দুটির ইন্টারসেকশন করলে এমন একটি টাইপ তৈরি হবে যার মাঝে দুই ধরনের প্রপার্টিই থাকতে হবে।
TypeScript
// ইউনিয়ন টাইপ (OR)
type StringOrNumber = string | number;
let score: StringOrNumber = 100;
score = "One Hundred"; // কোনো এরর আসবে না// ইন্টারসেকশন টাইপ (AND)
type Person = { name: string };
type Employee = { salary: number };
type Worker = Person & Employee; // name এবং salary দুটোই থাকা বাধ্যতামূলকconst staff: Worker = {
name: "David",
salary: 50000
};
Question 13: Ternary Operator, Nullish Coalescing & Optional Chaining
Short Answer:
These three features handle conditional logic and undefined data cleanly:
- Ternary Operator (
? :) is a shorthand forif-else. - Nullish Coalescing (
??) provides a default value only if the left side is exactlynullorundefined. - Optional Chaining (
?.) prevents app crashes by stopping execution if it tries to read a property from an undefined or null object.
Detailed Answer:
These tools prevent writing deeply nested if blocks.
- Ternary: Evaluates a condition. If true, runs the first expression; if false, runs the second.
- Nullish Coalescing: Unlike the logical OR (
||) which triggers on any falsy value (like0or""),??strictly checks fornullorundefined. This is crucial when0or empty strings are valid data. - Optional Chaining: When querying an API, nested properties might not exist yet.
user?.address?.citywill returnundefinedinstead of throwing a fatal error ifaddressis missing.
TypeScript
// 1. Ternary Operator
const age = 20;
const status = age >= 18 ? "Adult" : "Minor";// 2. Nullish Coalescing
const inputAmount = 0;
const balance1 = inputAmount || 100; // Returns 100 (falsy check)
const balance2 = inputAmount ?? 100; // Returns 0 (strict null check)// 3. Optional Chaining
const user = { profile: { name: "Sarah" } };
// No error if address is undefined, just returns undefined
console.log(user?.address?.city);
প্রশ্ন ১৩: টারনারি অপারেটর, নালিশ কোয়ালিসিং এবং অপশনাল চেইনিং
সংক্ষিপ্ত উত্তর:
এই তিনটি ফিচার কোডের কন্ডিশন এবং অজানা ডেটা খুব সুন্দরভাবে হ্যান্ডেল করে:
১. টারনারি অপারেটর (? :) হলো if-else স্টেটমেন্টের শর্টকাট।
২. নালিশ কোয়ালিসিং (??) একটি ডিফল্ট ভ্যালু রিটার্ন করে শুধুমাত্র যদি বাম পাশের মান ঠিক null বা undefined হয়।
৩. অপশনাল চেইনিং (?.) কোনো অবজেক্টের অস্তিত্ব না থাকলে প্রোগ্রাম ক্র্যাশ করা থেকে বাঁচায় এবং সরাসরি undefined রিটার্ন করে।
বিস্তারিত উত্তর:
এই টুলসগুলো বড় এবং নেস্টেড if ব্লক লেখার হাত থেকে বাঁচায়।
- টারনারি: একটি শর্ত চেক করে। সত্য হলে প্রথম অংশ এবং মিথ্যা হলে দ্বিতীয় অংশ কাজ করে।
- নালিশ কোয়ালিসিং: লজিক্যাল OR (
||) যেকোনো ফলসি (falsy) ভ্যালু (যেমন-0বা"")-কে বাতিল করে দেয়। কিন্তু??শুধুমাত্রnullবাundefinedচেক করে। যখন0একটি ভ্যালিড ডেটা, তখন এটি খুবই দরকারি। - অপশনাল চেইনিং: এপিআই থেকে ডেটা আনলে অনেক সময় ভেতরের প্রপার্টি থাকে না।
user?.address?.cityলিখলেaddressনা থাকলেও কোড ক্র্যাশ না করেundefinedরিটার্ন করবে।
TypeScript
// ১. টারনারি অপারেটর
const age = 20;
const status = age >= 18 ? "Adult" : "Minor";// ২. নালিশ কোয়ালিসিং
const inputAmount = 0;
const balance1 = inputAmount || 100; // আউটপুট: 100 (ফলসি চেক)
const balance2 = inputAmount ?? 100; // আউটপুট: 0 (স্ট্রিক্ট নাল চেক)// ৩. অপশনাল চেইনিং
const user = { profile: { name: "Sarah" } };
// address না থাকলে ক্র্যাশ করবে না, শুধু undefined রিটার্ন করবে
console.log(user?.address?.city);
Question 14: Type Assertion
Short Answer:
Type assertion is a mechanism that allows you to override TypeScript’s inferred type by telling the compiler, “Trust me, I know exactly what type this value is.” It is typically performed using the as keyword.
Detailed Answer:
TypeScript is smart, but sometimes you, as the developer, have contextual information that the compiler does not. For example, when you select a DOM element, TypeScript only knows it is an HTMLElement. You have to assert that it is specifically an HTMLInputElement to access its value property without throwing a type error.
Caution: Type assertion does not restructure or cast the actual data at runtime. It only mutes the compiler’s warnings. If you assert a string as a number, it will still behave as a string at runtime, potentially causing bugs.
TypeScript
// Type Assertion using 'as'
let unknownValue: unknown = "This is a string";
// We assert that unknownValue is definitely a string to use string methods
let strLength: number = (unknownValue as string).length;// Common DOM scenario
const inputElement = document.getElementById("myInput") as HTMLInputElement;
console.log(inputElement.value);প্রশ্ন ১৪: টাইপ অ্যাসারশন (Type Assertion)
সংক্ষিপ্ত উত্তর:
টাইপ অ্যাসারশন হলো এমন একটি উপায় যার মাধ্যমে টাইপস্ক্রিপ্ট কম্পাইলারকে ওভাররাইড করে বলা যায় যে, “এই ভ্যালুটির টাইপ কী হবে তা আমি নিশ্চিতভাবে জানি।” এটি সাধারণত as কি-ওয়ার্ড ব্যবহার করে করা হয়।
বিস্তারিত উত্তর:
টাইপস্ক্রিপ্ট যথেষ্ট স্মার্ট হলেও কিছু নির্দিষ্ট ক্ষেত্রে একজন ডেভেলপার হিসেবে আপনি টাইপ সম্পর্কে বেশি ভালো ধারণা রাখেন। উদাহরণস্বরূপ, যখন আপনি DOM থেকে কোনো এলিমেন্ট সিলেক্ট করেন, টাইপস্ক্রিপ্ট শুধু জানে সেটি একটি সাধারণ HTMLElement। এর value প্রপার্টি অ্যাক্সেস করতে হলে আপনাকে অ্যাসার্ট করে বলে দিতে হবে যে এটি নির্দিষ্টভাবে একটি HTMLInputElement।
সতর্কতা: টাইপ অ্যাসারশন রানটাইমে ডেটা পরিবর্তন করে না। এটি শুধু কম্পাইল টাইমে টাইপস্ক্রিপ্টের এরর বন্ধ করে। তাই ভুল অ্যাসারশন করলে পরবর্তীতে বাগ তৈরি হতে পারে।
TypeScript
// 'as' ব্যবহার করে টাইপ অ্যাসারশন
let unknownValue: unknown = "This is a string";
// আমরা অ্যাসার্ট করছি যে এটি নিশ্চিত স্ট্রিং, তাই আমরা length মেথড ব্যবহার করতে পারছি
let strLength: number = (unknownValue as string).length;// DOM ম্যানিপুলেশনের ক্ষেত্রে
const inputElement = document.getElementById("myInput") as HTMLInputElement;
console.log(inputElement.value);Question 15: Type Interface
Short Answer:
An interface in TypeScript is a powerful syntactical contract that defines the specific structure, properties, and methods an object or a class must possess. It is the core tool for defining object shapes in TypeScript.
Detailed Answer:
Think of an interface as a blueprint. If an object is built using that blueprint, it guarantees that the object will have the exact keys and data types outlined in the interface. Interfaces are extensively used in Object-Oriented Programming (OOP) to define contracts that classes must implement.
They support optional properties (?) and readonly properties, making them extremely robust for defining API models, component props, and complex object structures.
TypeScript
interface Car {
brand: string;
model: string;
year?: number; // Optional
readonly chassisNumber: string; // Cannot be modified after creation
}const myCar: Car = {
brand: "Toyota",
model: "Corolla",
chassisNumber: "A1B2C3D4"
};
// myCar.chassisNumber = "XYZ"; // Error: Cannot assign to 'chassisNumber' because it is a read-only property.প্রশ্ন ১৫: টাইপ ইন্টারফেস (Type Interface)
সংক্ষিপ্ত উত্তর:
টাইপস্ক্রিপ্টে interface হলো একটি কন্ট্যাক্ট বা ব্লু-প্রিন্ট যা নির্ধারণ করে দেয় একটি অবজেক্ট বা ক্লাসের স্ট্রাকচার, প্রপার্টি এবং মেথডগুলো কেমন হবে। অবজেক্টের শেইপ (shape) বা গঠন ঠিক করার জন্য এটি সবচেয়ে বেশি ব্যবহৃত হয়।
বিস্তারিত উত্তর:
ইন্টারফেসকে একটি নকশা হিসেবে চিন্তা করতে পারেন। কোনো অবজেক্ট যদি ওই নকশা অনুসরণ করে তৈরি হয়, তবে ওই অবজেক্টে ইন্টারফেসের উল্লেখ করা সবগুলো প্রপার্টি এবং সঠিক টাইপ থাকতে হবে। অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং (OOP)-এ ক্লাসের নিয়মকানুন ঠিক করে দেওয়ার জন্য ইন্টারফেস সবচেয়ে বেশি ব্যবহৃত হয়।
এতে অপশনাল প্রপার্টি (?) এবং রিড-অনলি (readonly) প্রপার্টিও ব্যবহার করা যায়, যা এপিআই মডেল বা কম্পোনেন্ট প্রপস ডিফাইন করার জন্য দারুণ কার্যকরী।
TypeScript
interface Car {
brand: string;
model: string;
year?: number; // অপশনাল
readonly chassisNumber: string; // তৈরির পর আর পরিবর্তন করা যাবে না
}const myCar: Car = {
brand: "Toyota",
model: "Corolla",
chassisNumber: "A1B2C3D4"
};
// myCar.chassisNumber = "XYZ"; // Error: রিড-অনলি হওয়ায় পরিবর্তন করা যাবে নাQuestion 16: Difference between Interface and Normal Type (Type Alias)
Short Answer:
Both interface and type can define the shape of an object. The main difference is that an interface can only describe object/class structures and can be dynamically merged (Declaration Merging). A type alias can describe objects as well as primitives, unions, and tuples, but it cannot be dynamically merged once declared.
Detailed Answer:
The choice between type and interface is a common debate, but understanding their limitations clarifies when to use which:
- Scope:
typeis highly versatile. You can use it to create union types (type ID = string | number) and tuples.interfacestrictly works with object shapes and class implementations. - Merging (Declaration Merging): If you define two interfaces with the exact same name in the same scope, TypeScript automatically merges their properties together. If you try this with
type, TypeScript will throw a "Duplicate identifier" error. - Extending: Both can extend others. Interfaces use the
extendskeyword, while Types use the intersection&operator. For modern development,interfaceis generally preferred for defining structural models, whiletypeis reserved for specific utility types and unions.
TypeScript
// 1. Declaration Merging (Only Interface can do this)
interface User { name: string; }
interface User { age: number; }
// The User interface now requires BOTH name and age.const p1: User = { name: "Alex", age: 25 }; // 2. Union and Primitive (Only Type can do this)
type Status = "success" | "error"; // Interface cannot do this// 3. Extending
interface Animal { species: string; }
interface Dog extends Animal { bark: boolean; } // Interface extendtype Vehicle = { wheels: number };
type Car = Vehicle & { brand: string }; // Type extend (Intersection)
প্রশ্ন ১৬: ইন্টারফেস (Interface) এবং নরমাল টাইপের (Type Alias) মধ্যে পার্থক্য
সংক্ষিপ্ত উত্তর:
interface এবং type উভয়ই অবজেক্টের গঠন তৈরি করতে পারে। মূল পার্থক্য হলো, interface শুধুমাত্র অবজেক্ট বা ক্লাসের জন্য কাজ করে এবং একই নামে একাধিকবার ডিক্লেয়ার করলে সেগুলো নিজে থেকেই একত্রিত (Merge) হয়ে যায়। অন্যদিকে, type দিয়ে অবজেক্ট ছাড়াও প্রিমিটিভ, ইউনিয়ন বা টাপল তৈরি করা যায়, তবে এটি একবার ডিক্লেয়ার করার পর আর একত্রিত (Merge) করা যায় না।
বিস্তারিত উত্তর:
কখন কোনটি ব্যবহার করবেন তা নির্ভর করে তাদের ফিচারের ওপর:
১. স্কোপ: type অনেক বেশি ফ্লেক্সিবল। আপনি এটি দিয়ে ইউনিয়ন টাইপ (type ID = string | number) বানাতে পারবেন যা ইন্টারফেস দিয়ে সম্ভব নয়। ইন্টারফেস শুধুমাত্র অবজেক্ট শেইপের জন্য সীমাবদ্ধ।
২. মার্জিং (Declaration Merging): একই নামে দুটি ইন্টারফেস তৈরি করলে টাইপস্ক্রিপ্ট স্বয়ংক্রিয়ভাবে তাদের প্রপার্টিগুলো একসাথে জোড়া লাগিয়ে দেয়। কিন্তু একই নামে দুটি type তৈরি করতে গেলে ডুপ্লিকেট এরর আসবে।
৩. এক্সটেন্ড (Extending): ইন্টারফেস নতুন কিছু যুক্ত করার জন্য extends কি-ওয়ার্ড ব্যবহার করে। অন্যদিকে type ইন্টারসেকশন (&) ব্যবহার করে। সাধারণত প্রজেক্টের অবজেক্ট মডেলিংয়ের জন্য ইন্টারফেস এবং অন্যান্য জটিল টাইপের জন্য টাইপ এলিয়াস ব্যবহার করা হয়।
TypeScript
// ১. ডিক্লারেশন মার্জিং (শুধুমাত্র ইন্টারফেস পারে)
interface User { name: string; }
interface User { age: number; }
// এখন User ইন্টারফেসে name এবং age দুটোই থাকতে হবেconst p1: User = { name: "Alex", age: 25 }; // ২. ইউনিয়ন টাইপ (শুধুমাত্র Type পারে)
type Status = "success" | "error"; // ৩. এক্সটেন্ড করা
interface Animal { species: string; }
interface Dog extends Animal { bark: boolean; } // ইন্টারফেস এক্সটেন্ডtype Vehicle = { wheels: number };
type Car = Vehicle & { brand: string }; // টাইপ এক্সটেন্ড (ইন্টারসেকশন)
Phase 3: Interfaces Deep Dive & Generics
Question 17: Interface Extends & When to use which
Short Answer:
The extends keyword allows an interface to inherit properties and methods from one or multiple other interfaces, promoting code reusability and keeping your models strictly organized. As a general rule of thumb, use interface when defining object shapes, class structures, or public APIs, and use type for unions, intersections, primitives, and complex mapped types.
Detailed Answer:
Inheritance in TypeScript interfaces works similarly to class inheritance in Object-Oriented Programming, but with added flexibility.
- Multiple Inheritance: Unlike classes in many languages, a single interface can extend multiple interfaces simultaneously, separated by commas.
- When to use what: If you are building a library or an open-source tool,
interfaceis preferred because users can extend it via "Declaration Merging". If you need to define a specific state that can be one of several values (liketype Status = "Loading" | "Success"), you must usetype.
TypeScript
interface Person {
name: string;
age: number;
}interface Employee {
employeeId: number;
}// Inheriting from multiple interfaces
interface Manager extends Person, Employee {
department: string;
}const manager: Manager = {
name: "John",
age: 40,
employeeId: 101,
department: "IT"
};
প্রশ্ন ১৭: ইন্টারফেস এক্সটেন্ডস (Interface Extends) এবং কখন কোনটি ব্যবহার করবেন
সংক্ষিপ্ত উত্তর:
extends কি-ওয়ার্ড ব্যবহার করে একটি ইন্টারফেস অন্য এক বা একাধিক ইন্টারফেসের প্রপার্টি এবং মেথড ইনহেরিট (inherit) বা উত্তরাধিকারসূত্রে গ্রহণ করতে পারে। এটি কোডকে পুনরায় ব্যবহারযোগ্য করে তোলে। সাধারণ নিয়ম হলো- অবজেক্টের গঠন, ক্লাসের স্ট্রাকচার বা এপিআই (API) ডিফাইন করতে interface ব্যবহার করুন। আর প্রিমিটিভ, ইউনিয়ন বা জটিল টাইপের ক্ষেত্রে type ব্যবহার করুন।
বিস্তারিত উত্তর:
টাইপস্ক্রিপ্ট ইন্টারফেসে ইনহেরিটেন্স অনেকটা অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংয়ের (OOP) মতো কাজ করে, তবে এটি আরও ফ্লেক্সিবল।
১. মাল্টিপল ইনহেরিটেন্স: ক্লাসের মতো সীমাবদ্ধতা এখানে নেই। একটি ইন্টারফেস একই সাথে কমা (,) দিয়ে একাধিক ইন্টারফেসকে এক্সটেন্ড করতে পারে।
২. কখন কোনটি ব্যবহার করবেন: আপনি যদি কোনো লাইব্রেরি বানান, তবে interface ব্যবহার করা ভালো কারণ ব্যবহারকারীরা চাইলে ডিক্লারেশন মার্জিংয়ের মাধ্যমে এতে নতুন কিছু যুক্ত করতে পারবে। তবে একাধিক অবস্থার কোনো একটি বোঝাতে (যেমন- type Status = "Loading" | "Success") আপনাকে অবশ্যই type ব্যবহার করতে হবে।
Question 18: Array Index Interface (Index Signatures)
Short Answer:
Array index interfaces, or index signatures, allow you to define the type of keys and values when the exact property names are unknown beforehand. It is highly useful for creating dynamic objects like dictionaries or custom arrays where you only know that the keys are of type number or string, and the values hold a specific type.
Detailed Answer:
Sometimes you don’t know the exact names of the properties an object will have, but you do know the shape of the values.
- Dynamic Objects: You can enforce that an object can have any number of string keys, but every value must be a string or number.
- Custom Arrays: Since arrays in JavaScript are fundamentally objects with numeric keys, you can use an index signature to strictly type a custom array-like structure.
TypeScript
// Index Signature for a dynamic object (Dictionary)
interface ErrorDictionary {
[key: string]: string; // Key is string, Value is string
}
const errors: ErrorDictionary = {
emailEmpty: "Email cannot be empty",
passwordWeak: "Password is too short"
};// Index Signature for an Array-like structure
interface StringArray {
[index: number]: string; // Key is number, Value is string
}
const fruits: StringArray = ["Apple", "Banana", "Mango"];প্রশ্ন ১৮: অ্যারে ইনডেক্স ইন্টারফেস বা ইনডেক্স সিগনেচার (Array Index Interface)
সংক্ষিপ্ত উত্তর:
যখন কোনো অবজেক্টের প্রপার্টির নাম আগে থেকে জানা থাকে না, তখন ইনডেক্স সিগনেচার ব্যবহার করে আমরা নির্ধারণ করে দিতে পারি যে তার কি (key) এবং ভ্যালুর (value) টাইপ কী হবে। ডাইনামিক অবজেক্ট (যেমন ডিকশনারি) বা কাস্টম অ্যারে তৈরির ক্ষেত্রে এটি দারুণ কাজ করে, যেখানে কি (key) স্ট্রিং বা নাম্বার হতে পারে এবং ভ্যালু নির্দিষ্ট টাইপের হয়।
বিস্তারিত উত্তর:
মাঝেমধ্যে অবজেক্টের প্রপার্টির নাম আমাদের অজানা থাকতে পারে, তবে আমরা জানি সেই প্রপার্টির ডেটা টাইপ কী হবে।
১. ডাইনামিক অবজেক্ট: আপনি চাইলে এমন নিয়ম করে দিতে পারেন যে, অবজেক্টে ইচ্ছামতো নাম দিয়ে ডেটা রাখা যাবে, কিন্তু সবগুলোর ভ্যালু অবশ্যই স্ট্রিং বা নাম্বার হতে হবে।
২. কাস্টম অ্যারে: যেহেতু জাভাস্ক্রিপ্টে অ্যারেগুলো মূলত নাম্বার কি (numeric key) ভিত্তিক অবজেক্ট, তাই ইনডেক্স সিগনেচার ব্যবহার করে আপনি কাস্টম অ্যারে স্ট্রাকচারও তৈরি করতে পারেন।
Question 19: Interface in Function
Short Answer:
Interfaces can be used to describe the exact signature of a function, not just object properties. By defining the parameters and the return type inside an interface without providing a property name, you can standardize callback functions or method signatures across different parts of your application cleanly.
Detailed Answer:
While we usually think of interfaces as object shapes, they are perfectly capable of strictly defining standalone functions. This is incredibly useful when passing callback functions as arguments, ensuring that the callback receives the correct arguments and returns the expected result. It encapsulates the function logic tightly.
TypeScript
// Defining a function signature using an interface
interface MathOperation {
(a: number, b: number): number;
}// Using the interface
const add: MathOperation = (x, y) => {
return x + y;
};const multiply: MathOperation = (x, y) => {
return x * y;
};console.log(add(5, 10)); // 15
প্রশ্ন ১৯: ফাংশনের ক্ষেত্রে ইন্টারফেস (Interface in Function)
Get Yeasaleh’s stories in your inbox
Join Medium for free to get updates from this writer.
সংক্ষিপ্ত উত্তর:
ইন্টারফেস শুধু অবজেক্টের প্রপার্টি নয়, বরং একটি ফাংশনের গঠন বা সিগনেচার নির্ধারণ করতেও ব্যবহার করা যায়। ইন্টারফেসের ভেতরে কোনো প্রপার্টির নাম ছাড়াই শুধু প্যারামিটার এবং রিটার্ন টাইপ উল্লেখ করে কলব্যাক ফাংশন বা মেথডগুলোকে স্ট্যান্ডার্ড এবং সুরক্ষিত করা যায়।
বিস্তারিত উত্তর:
আমরা সাধারণত ইন্টারফেস বলতে অবজেক্টের নকশাকে বুঝি, তবে এটি ফাংশনের টাইপ নির্ধারণের ক্ষেত্রেও চমৎকার কাজ করে। যখন আমরা এক ফাংশনের ভেতরে অন্য ফাংশনকে আর্গুমেন্ট (কলব্যাক) হিসেবে পাস করি, তখন সেই ফাংশনটি ঠিক কী কী আর্গুমেন্ট নেবে এবং কী রিটার্ন করবে, তা ইন্টারফেস দিয়ে আগে থেকেই নির্দিষ্ট করে দেওয়া যায়।
Question 20: Generics in TypeScript
Short Answer:
Generics are a powerful feature that allows you to create reusable, flexible code components (functions, classes, interfaces) that can work with a variety of data types rather than a single specific one. Think of generics as “variables for types” — they hold the place for a type that will be provided later during execution.
Detailed Answer:
Before generics, if you wanted a function to accept any type of data, you had to use the any type. However, using any completely destroys TypeScript's type-checking ability, meaning you lose intellisense and safety.
Generics solve this by capturing the type of the data passed in and locking it. Represented usually by <T> (Type), it ensures that if you pass a string in, TypeScript strictly enforces that a string comes out.
TypeScript
// Without Generics (Loses type safety)
function echoAny(data: any): any {
return data;
}// With Generics (Preserves exact type)
function echoGeneric<T>(data: T): T {
return data;
}const res1 = echoGeneric<string>("Hello"); // TypeScript knows res1 is a string
const res2 = echoGeneric<number>(100); // TypeScript knows res2 is a number
প্রশ্ন ২০: টাইপস্ক্রিপ্টে জেনেরিকস (Generics in TypeScript)
সংক্ষিপ্ত উত্তর:
জেনেরিকস হলো এমন একটি শক্তিশালী ফিচার যার মাধ্যমে রিইউজেবল এবং ফ্লেক্সিবল কোড (ফাংশন, ক্লাস, ইন্টারফেস) তৈরি করা যায়, যা নির্দিষ্ট একটি টাইপের বদলে বিভিন্ন ধরনের ডেটা টাইপ নিয়ে কাজ করতে পারে। জেনেরিকসকে “টাইপের জন্য ভেরিয়েবল” হিসেবে চিন্তা করতে পারেন, যা কোড রান করার সময় আসল টাইপটি গ্রহণ করে।
বিস্তারিত উত্তর:
জেনেরিকস আসার আগে, কোনো ফাংশনে যেকোনো ধরনের ডেটা পাস করতে হলে আমাদের any টাইপ ব্যবহার করতে হতো। কিন্তু any ব্যবহার করলে টাইপস্ক্রিপ্টের টাইপ-চেকিং ক্ষমতা নষ্ট হয়ে যায়।
জেনেরিকস এই সমস্যার সমাধান করেছে। এটি মূলত ডেটার টাইপটিকে ক্যাপচার বা ধরে রাখে। সাধারণত এটি <T> (Type) দিয়ে প্রকাশ করা হয়। এর মানে হলো, আপনি যদি ফাংশনে স্ট্রিং পাস করেন, টাইপস্ক্রিপ্ট নিশ্চিত করবে যে আউটপুটও স্ট্রিংই হবে।
Question 21: Generics in Array and Object
Short Answer:
Applying generics to arrays and objects allows you to define highly dynamic data structures where the internal data types are specified at the time of their creation. For arrays, you can use the built-in generic syntax Array<T>, and for objects, you can define properties whose types are dynamically passed as generic parameters.
Detailed Answer:
- Generic Arrays: Instead of writing
string[], you can writeArray<string>. This is the exact same thing but written using the generic syntax. - Generic Objects: When creating wrappers (like API response objects), the exact shape of the inner data might change. By making the object structure generic, you can pass the specific interface of the data when initializing the object, making it infinitely reusable.
TypeScript
// Generic Array
const stringScores: Array<string> = ["Ninety", "Eighty"];
const numberScores: Array<number> = [90, 80];// Generic Object
type APIResponse<T> = {
status: number;
message: string;
data: T; // The type of 'data' is dynamic
};const userRes: APIResponse<{ name: string }> = {
status: 200,
message: "Success",
data: { name: "Alice" }
};
প্রশ্ন ২১: অ্যারে এবং অবজেক্টে জেনেরিকস (Generics in Array and Object)
সংক্ষিপ্ত উত্তর:
অ্যারে এবং অবজেক্টে জেনেরিকস প্রয়োগ করে আমরা এমন ডাইনামিক ডেটা স্ট্রাকচার তৈরি করতে পারি, যার ভেতরের ডেটার টাইপ আগে থেকে ফিক্সড না করে ব্যবহারের সময় নির্ধারণ করা যায়। অ্যারের ক্ষেত্রে বিল্ট-ইন জেনেরিক সিনট্যাক্স Array<T> ব্যবহার করা যায়, এবং অবজেক্টের ক্ষেত্রে প্রপার্টির টাইপ ডাইনামিকভাবে পাস করা যায়।
বিস্তারিত উত্তর:
১. জেনেরিক অ্যারে: আপনি string[] লেখার বদলে Array<string> লিখতে পারেন। এটি মূলত একই কাজ করে, তবে জেনেরিক সিনট্যাক্স ব্যবহার করে লেখা।
২. জেনেরিক অবজেক্ট: এপিআই (API) রেসপন্সের মতো অবজেক্ট তৈরির সময় ভেতরের মূল ডেটার স্ট্রাকচার একেক সময় একেক রকম হতে পারে। অবজেক্টকে জেনেরিক করলে, ডিক্লেয়ার করার সময় বলে দেওয়া যায় যে এবার ডেটার ভেতরে কী টাইপ আসবে। এতে একটি অবজেক্ট মডেলকে বারবার ব্যবহার করা যায়।
Question 22: Generics with Interfaces and Functions
Short Answer:
You can pass generic type parameters to both functions and interfaces to make them adaptable to multiple scenarios. A generic function captures the exact type of the arguments passed to it dynamically, while a generic interface acts as a blank template where the specific property types are defined upon implementation.
Detailed Answer:
Combining functions and interfaces with generics is the cornerstone of modern TypeScript development (especially in frameworks like React or NestJS).
You define an interface that takes a generic parameter <T, U>, and then you use that interface as the return type or parameter type in a generic function. This ensures that the data flows seamlessly and safely across different layers of your application.
TypeScript
// Generic Interface
interface Pair<T, U> {
first: T;
second: U;
}// Generic Function using the Generic Interface
function makePair<T, U>(a: T, b: U): Pair<T, U> {
return { first: a, second: b };
}// Usage
const pair1 = makePair<string, number>("Age", 25);
const pair2 = makePair<boolean, string>(true, "Success");
প্রশ্ন ২২: ইন্টারফেস এবং ফাংশনের সাথে জেনেরিকস (Generics with Interfaces and Functions)
সংক্ষিপ্ত উত্তর:
ফাংশন এবং ইন্টারফেস উভয় ক্ষেত্রেই জেনেরিক প্যারামিটার পাস করে এগুলোকে বিভিন্ন পরিস্থিতির জন্য উপযোগী করা যায়। একটি জেনেরিক ফাংশন তার আর্গুমেন্টের টাইপ ডাইনামিকভাবে বুঝে নেয়, আর জেনেরিক ইন্টারফেস একটি ফাঁকা টেমপ্লেট হিসেবে কাজ করে যার প্রপার্টির টাইপগুলো ব্যবহারের সময় নির্ধারণ করা হয়।
বিস্তারিত উত্তর:
জেনেরিকস দিয়ে ফাংশন ও ইন্টারফেসকে যুক্ত করা আধুনিক টাইপস্ক্রিপ্ট ডেভেলপমেন্টের (যেমন- রিয়্যাক্ট বা নেক্সট জেএস) একটি বড় অংশ।
আপনি এমন একটি ইন্টারফেস তৈরি করতে পারেন যা <T, U> এর মতো জেনেরিক প্যারামিটার নেয়। এরপর সেই ইন্টারফেসটিকে একটি জেনেরিক ফাংশনের রিটার্ন টাইপ হিসেবে ব্যবহার করতে পারেন। এটি অ্যাপ্লিকেশনের বিভিন্ন অংশের মাঝে অত্যন্ত সুরক্ষিতভাবে ডেটা আদান-প্রদান নিশ্চিত করে।
Question 23: Constraints with TypeScript (Generic Constraints)
Short Answer:
Generic constraints limit the kinds of types that can be passed into a generic parameter by using the extends keyword. Instead of allowing literally any type to be passed to <T>, constraints ensure that the provided type satisfies a minimum requirement, such as containing specific properties or methods.
Detailed Answer:
By default, a generic <T> can be absolutely anything. This becomes a problem if you try to access a specific property inside the function. For instance, if you try to access arg.length, TypeScript will throw an error because it doesn't know if T has a length property (e.g., a number doesn't).
To solve this, we constrain the generic to an interface that possesses the required property. Now, TypeScript will only accept variables that have a length property (like strings or arrays).
TypeScript
// Defining the constraint constraint
interface HasLength {
length: number;
}// T must have a 'length' property
function logLength<T extends HasLength>(arg: T): void {
console.log(arg.length);
}logLength("Hello World"); // Valid (String has length)
logLength([1, 2, 3]); // Valid (Array has length)
// logLength(100); // Error: number doesn't have a 'length' property
প্রশ্ন ২৩: জেনেরিকসের সাথে কনস্ট্রেইন্ট (Constraints with TypeScript)
সংক্ষিপ্ত উত্তর:
জেনেরিক কনস্ট্রেইন্টস extends কি-ওয়ার্ড ব্যবহার করে জেনেরিক প্যারামিটারে পাস করা টাইপের ওপর সীমাবদ্ধতা তৈরি করে। এটি <T> এর জায়গায় যেকোনো কিছু পাস করতে বাধা দেয় এবং নিশ্চিত করে যে পাস করা টাইপের মধ্যে কমপক্ষে কিছু নির্দিষ্ট প্রপার্টি বা মেথড অবশ্যই থাকতে হবে।
বিস্তারিত উত্তর:
ডিফল্টভাবে জেনেরিক <T> যেকোনো কিছু হতে পারে। কিন্তু ফাংশনের ভেতরে যদি আপনি কোনো নির্দিষ্ট প্রপার্টি অ্যাক্সেস করতে চান তখন এটি সমস্যা তৈরি করে। যেমন- আপনি যদি arg.length বের করতে চান, টাইপস্ক্রিপ্ট এরর দেবে, কারণ সে জানে না যে T এর মধ্যে আদৌ length প্রপার্টি আছে কিনা (যেমন নাম্বারের length থাকে না)।
এর সমাধানের জন্য আমরা কনস্ট্রেইন্ট ব্যবহার করি। এতে টাইপস্ক্রিপ্ট শুধুমাত্র সেসব ডেটাই গ্রহণ করবে যেগুলোর length প্রপার্টি রয়েছে (যেমন- স্ট্রিং বা অ্যারে)।
Question 24: keyof Constraint with Generics
Short Answer:
The keyof operator takes an object type and produces a literal union of its keys. When combined with generics as a constraint (<T, K T extends keyof>), it allows you to create highly secure functions that guarantee dynamically that a provided string key actually exists on the specific object passed to the function.
Detailed Answer:
This is one of the most powerful features for writing utility functions in TypeScript. Imagine you have a function that takes an object and a property name, and returns the value of that property.
Without keyof, you might accidentally pass a property name that doesn't exist on the object, resulting in undefined. By constraining the key K to extends keyof T, TypeScript actively checks the object's keys and throws an error at compile-time if you misspell the key or request a non-existent one.
TypeScript
// K must be a valid key of T
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}const developer = {
name: "John",
skill: "TypeScript",
experience: 5
};const devName = getProperty(developer, "name"); // Valid
const devSkill = getProperty(developer, "skill"); // Valid
// const devSalary = getProperty(developer, "salary");
// Error: Argument of type '"salary"' is not assignable to parameter of type '"name" | "skill" | "experience"'.
প্রশ্ন ২৪: জেনেরিকসের সাথে keyof কনস্ট্রেইন্ট (keyof Constraint with Generics)
সংক্ষিপ্ত উত্তর:
keyof অপারেটর একটি অবজেক্ট টাইপ থেকে তার কি (keys)-গুলো নিয়ে একটি ইউনিয়ন তৈরি করে। জেনেরিক কনস্ট্রেইন্টের সাথে এটি ব্যবহার করলে (<T, K T extends keyof>) এমন সুরক্ষিত ফাংশন তৈরি করা যায়, যা গ্যারান্টি দেয় যে আপনি অবজেক্টের ভেতর থেকে যে প্রপার্টিটি খুঁজছেন তা আসলেই ওই অবজেক্টে বিদ্যমান আছে।
বিস্তারিত উত্তর:
টাইপস্ক্রিপ্টে ইউটিলিটি ফাংশন লেখার জন্য এটি সবচেয়ে শক্তিশালী ফিচারগুলোর একটি। ধরুন, আপনার একটি ফাংশন আছে যা একটি অবজেক্ট এবং প্রপার্টির নাম ইনপুট হিসেবে নেয় এবং ওই প্রপার্টির ভ্যালু রিটার্ন করে।
keyof ব্যবহার না করলে আপনি ভুল করে এমন প্রপার্টি পাস করতে পারেন যা অবজেক্টে নেই, ফলে আউটপুট undefined আসবে। কিন্তু K extends keyof T ব্যবহার করলে টাইপস্ক্রিপ্ট অবজেক্টের প্রপার্টিগুলো স্ক্যান করে এবং ভুল নাম দিলে সাথে সাথেই এরর থ্রো করে।
(আপনার লিস্টের Phase 3 সম্পন্ন হলো। OOP, Enum, Utility Types এবং অন্যান্য টপিকগুলো নিয়ে পরবর্তী Phase জেনারেট করার জন্য অনুগ্রহ করে জানান!)
Phase 4: Enums, Advanced Types & Type Guards
Question 25: Explore Enum in TypeScript
Short Answer:
An Enum (Enumeration) is a special “class” in TypeScript that represents a group of named constant values. It makes it easier to handle sets of related values, such as user roles, directions, or order statuses, by replacing magic numbers or scattered strings with strictly typed, readable names.
Detailed Answer:
Enums allow developers to define a set of named constants. TypeScript supports both numeric and string-based enums.
- Numeric Enums: By default, enums are zero-based. If you don’t assign a value, the first item is
0, the next is1, and so on. You can also customize the starting number. - String Enums: These are often preferred because they are more readable when debugging. Each member must be explicitly initialized with a string value.
- Usage: Enums are great for standardizing finite states in your application, preventing typos that occur when using raw strings.
TypeScript
// Numeric Enum
enum Direction {
Up = 1, // Starts at 1 instead of 0
Down, // 2
Left, // 3
Right // 4
}// String Enum
enum UserRole {
Admin = "ADMIN",
User = "USER",
Guest = "GUEST"
}const currentUserRole: UserRole = UserRole.Admin;
console.log(currentUserRole); // "ADMIN"
প্রশ্ন ২৫: টাইপস্ক্রিপ্টে এনাম (Enum) এর ব্যবহার
সংক্ষিপ্ত উত্তর:
এনাম (Enum বা Enumeration) হলো টাইপস্ক্রিপ্টের একটি বিশেষ বৈশিষ্ট্য যা কতগুলো নির্দিষ্ট কনস্ট্যান্ট (constant) ভ্যালুকে একটি গ্রুপ হিসেবে ধারণ করে। এটি অ্যাপ্লিকেশনের বিভিন্ন ফিক্সড অবস্থা (যেমন- ইউজারের রোল, অর্ডারের স্ট্যাটাস বা দিক) ম্যানেজ করতে ব্যবহৃত হয়, যা কোডকে আরও রিডেবল এবং টাইপ-সেইফ করে।
বিস্তারিত উত্তর:
এনামের মাধ্যমে ডেভেলপাররা নামের একটি নির্দিষ্ট তালিকা তৈরি করতে পারেন। টাইপস্ক্রিপ্ট মূলত দুই ধরনের এনাম সাপোর্ট করে:
১. নিউমেরিক এনাম (Numeric Enums): ডিফল্টভাবে এনামের মান ০ থেকে শুরু হয় এবং ক্রমান্বয়ে বাড়ে। আপনি চাইলে প্রথম মানটি পরিবর্তন করে দিলে পরের মানগুলো স্বয়ংক্রিয়ভাবে বাড়তে থাকবে।
২. স্ট্রিং এনাম (String Enums): ডিবাগ করার সুবিধার জন্য এটি বেশি ব্যবহৃত হয়। এখানে প্রতিটি প্রপার্টির মান স্ট্রিং হিসেবে নির্দিষ্ট করে দিতে হয়।
৩. ব্যবহার: অ্যাপ্লিকেশনের ফিক্সড ডেটা বা স্ট্যাটাসগুলো ম্যানেজ করার জন্য এটি খুব ভালো কাজ করে এবং সাধারণ স্ট্রিং ব্যবহারের ফলে হওয়া ভুল বানান থেকে রক্ষা করে।
Question 26: Why use as const instead of Enum?
Short Answer:
While Enums are useful, they generate extra boilerplate code (like IIFEs) when compiled into JavaScript, increasing bundle size. Using a standard object combined with the as const assertion provides the exact same type-safety and auto-completion as Enums, but compiles down to a plain JavaScript object without any unnecessary overhead.
Detailed Answer:
Many modern TypeScript developers prefer using Objects with as const over Enums for performance and simplicity.
- The Enum Overhead: When TypeScript compiles a standard Enum, it creates a two-way mapping object in JavaScript. This adds unnecessary code to the final bundle.
- The
as constSolution: Appendingas constto an object freezes it completely. TypeScript makes all propertiesreadonlyand treats the values as literal types rather than generic strings or numbers. - Extracting the Type: You can easily extract the literal values into a union type using
keyof typeof, mimicking Enum behavior perfectly without the runtime cost.
TypeScript
// The 'as const' approach
const Status = {
Pending: "PENDING",
Active: "ACTIVE",
Closed: "CLOSED"
} as const;// Extracting the literal types to use as a Type
type StatusType = typeof Status[keyof typeof Status];
// StatusType is exactly: "PENDING" | "ACTIVE" | "CLOSED"const myStatus: StatusType = Status.Active; // Strictly typed
প্রশ্ন ২৬: এনামের (Enum) বদলে as const কেন ব্যবহার করবেন?
সংক্ষিপ্ত উত্তর:
এনাম ব্যবহার করা সুবিধাজনক হলেও, এটি জাভাস্ক্রিপ্টে কম্পাইল হওয়ার সময় অতিরিক্ত কোড তৈরি করে যা ফাইলের সাইজ বাড়িয়ে দেয়। এর বদলে সাধারণ অবজেক্টের সাথে as const ব্যবহার করলে এনামের মতোই টাইপ-সেফটি এবং অটো-কমপ্লিশন পাওয়া যায়, কিন্তু এটি কোনো অতিরিক্ত রানটাইম কোড তৈরি করে না।
বিস্তারিত উত্তর:
পারফরম্যান্স এবং সিম্পলিসিটির জন্য অনেক আধুনিক ডেভেলপার এনামের বদলে as const ব্যবহার করতে পছন্দ করেন।
১. এনামের ওভারহেড: টাইপস্ক্রিপ্ট যখন এনাম কম্পাইল করে, তখন এটি জাভাস্ক্রিপ্টে একটি জটিল টু-ওয়ে ম্যাপিং অবজেক্ট তৈরি করে, যা ফাইলের সাইজ কিছুটা বাড়িয়ে দেয়।
২. as const এর সমাধান: অবজেক্টের শেষে as const জুড়ে দিলে অবজেক্টটি পুরোপুরি ফ্রিজ (freeze) হয়ে যায়। এর ফলে টাইপস্ক্রিপ্ট সব প্রপার্টিকে readonly করে দেয় এবং ভ্যালুগুলোকে লিটারাল টাইপ হিসেবে বিবেচনা করে।
৩. টাইপ বের করা: রানটাইমের কোনো ক্ষতি ছাড়াই keyof typeof ব্যবহার করে খুব সহজেই এই অবজেক্ট থেকে এনামের মতো একটি টাইপ তৈরি করা যায়।
Question 27: Using keyof and typeof together
Short Answer:
The typeof operator creates a TypeScript type based on an existing JavaScript runtime variable, while keyof extracts the keys from a type to create a union. When used together as keyof typeof, they allow you to automatically generate a union type of all the keys present in a standard JavaScript object without defining an interface manually.
Detailed Answer:
In a real-world project, you often have configuration objects or dictionaries where defining a separate type would violate the DRY (Don’t Repeat Yourself) principle.
typeof: First, it analyzes the JavaScript object and creates a silent TypeScript representation of it.keyof: Then, it iterates through that representation and plucks out only the keys.- This combination is incredibly powerful for keeping your types perfectly synced with your data structures. If you add a new key to the object, the type automatically updates itself.
TypeScript
const appConfig = {
theme: "dark",
language: "en",
version: "1.0.0"
};// 1. typeof appConfig creates the object type
// 2. keyof plucks the keys: "theme" | "language" | "version"
type ConfigKeys = keyof typeof appConfig;function updateConfig(key: ConfigKeys) {
console.log(`Updating ${key}`);
}updateConfig("theme"); // Valid
// updateConfig("autoUpdate"); // Error: Argument is not assignable to ConfigKeys
প্রশ্ন ২৭: keyof এবং typeof একসাথে ব্যবহার
সংক্ষিপ্ত উত্তর:
typeof অপারেটর একটি জাভাস্ক্রিপ্ট ভেরিয়েবল বা অবজেক্টকে স্ক্যান করে তার টাইপস্ক্রিপ্ট টাইপ তৈরি করে, আর keyof সেই টাইপ থেকে কি (keys)-গুলো বের করে। এই দুটি একসাথে (keyof typeof) ব্যবহার করলে কোনো আলাদা ইন্টারফেস তৈরি না করেই সরাসরি একটি জাভাস্ক্রিপ্ট অবজেক্টের সব কি (key) দিয়ে একটি ডাইনামিক ইউনিয়ন টাইপ তৈরি করা যায়।
বিস্তারিত উত্তর:
বাস্তব প্রজেক্টে আমাদের অনেক কনফিগারেশন অবজেক্ট থাকে, যেগুলোর জন্য আলাদা টাইপ লিখলে কোড বারবার রিপিট করতে হয়।
১. typeof: এটি প্রথমে জাভাস্ক্রিপ্ট অবজেক্টটিকে স্ক্যান করে তার একটি টাইপস্ক্রিপ্ট শেইপ তৈরি করে।
২. keyof: এরপর এটি সেই শেইপের ভেতর থেকে শুধু নাম বা কি (keys)-গুলো বের করে আনে।
এটি কোডকে ডাইনামিক রাখার জন্য দারুণ কার্যকরী। আপনি যদি মূল অবজেক্টে নতুন কোনো ডেটা যুক্ত করেন, তবে টাইপস্ক্রিপ্ট নিজে থেকেই ওই নতুন ডেটার টাইপ আপডেট করে নেবে।
Question 28: Explore Conditional Types
Short Answer:
Conditional Types in TypeScript function similarly to ternary operators (? :) in JavaScript, but they operate exclusively on types rather than values. They allow the type system to dynamically choose one of two possible types based on a logical condition (T extends U ? X : Y), making generic types highly intelligent and adaptable.
Detailed Answer:
Conditional types evaluate a relationship between types. The syntax is Condition ? TrueExpression : FalseExpression.
- How it works: You define a generic parameter. TypeScript checks if that parameter extends (or matches) a certain type. If it does, it returns type
A; otherwise, it returns typeB. - Real-world use: It is widely used in library development to create utility types that strip out
nullvalues, extract function return types, or modify nested object structures conditionally without hardcoding every possible scenario.
TypeScript
// Basic Conditional Type
type IsString<T> = T extends string ? "Yes, it's a string" : "No, it's not";type Check1 = IsString<string>; // Type is strictly "Yes, it's a string"
type Check2 = IsString<number>; // Type is strictly "No, it's not"// Practical Example: Removing null from a type
type NonNullableType<T> = T extends null | undefined ? never : T;type ValidName = NonNullableType<string | null>; // Resolves to 'string'
প্রশ্ন ২৮: কন্ডিশনাল টাইপস (Conditional Types)
সংক্ষিপ্ত উত্তর:
টাইপস্ক্রিপ্টে কন্ডিশনাল টাইপস অনেকটা জাভাস্ক্রিপ্টের টারনারি অপারেটরের (? :) মতোই কাজ করে, তবে এটি ভ্যালুর ওপর নয়, বরং টাইপের ওপর কাজ করে। এটি একটি লজিক্যাল শর্তের ওপর ভিত্তি করে ডাইনামিকভাবে টাইপ নির্ধারণ করতে সাহায্য করে (T extends U ? X : Y), যা জেনেরিক টাইপকে অনেক বেশি স্মার্ট করে তোলে।
বিস্তারিত উত্তর:
কন্ডিশনাল টাইপ মূলত দুটি টাইপের মাঝে সম্পর্ক চেক করে। এর সিনট্যাক্স হলো Condition ? TrueExpression : FalseExpression।
১. যেভাবে কাজ করে: আপনি একটি জেনেরিক প্যারামিটার ডিক্লেয়ার করেন। টাইপস্ক্রিপ্ট চেক করে ওই প্যারামিটারটি কোনো নির্দিষ্ট টাইপের সাথে ম্যাচ করে কিনা। করলে এটি একটি টাইপ রিটার্ন করে, না করলে অন্য টাইপ রিটার্ন করে।
২. বাস্তব ব্যবহার: বড় বড় লাইব্রেরি তৈরিতে এটি প্রচুর ব্যবহৃত হয়। নাল (null) ভ্যালু বাদ দেওয়া, ফাংশনের রিটার্ন টাইপ বের করা বা অবজেক্টের স্ট্রাকচার ডাইনামিকভাবে পরিবর্তন করতে এটি অত্যন্ত কার্যকরী।
Question 29: Explore Mapped Types
Short Answer:
Mapped Types allow you to construct an entirely new object type by iterating through the keys of an existing type and transforming them. By using the [K in keyof T] syntax, you can take a base interface and automatically generate variations of it, such as making every single property optional, readonly, or nullable without writing duplicate code.
Detailed Answer:
Imagine you have a large User interface with 20 properties. Later, you need an UpdateUser interface where all 20 properties are optional. Manually copying the interface and adding ? to everything is tedious and error-prone.
Mapped types solve this by acting like a for...in loop for types. It maps over the existing keys and applies a modifier. TypeScript's built-in Utility types (like Partial, Readonly) are actually built using Mapped Types under the hood.
TypeScript
interface UserProfile {
name: string;
age: number;
email: string;
}// Mapped Type: Making everything optional manually
type OptionalProfile<T> = {
[K in keyof T]?: T[K]; // Loops through each key K in T, adds '?'
};// Now name, age, and email are all optional
const updateData: OptionalProfile<UserProfile> = {
age: 30
};
প্রশ্ন ২৯: ম্যাপড টাইপস (Mapped Types)
সংক্ষিপ্ত উত্তর:
ম্যাপড টাইপস ব্যবহার করে একটি বিদ্যমান টাইপের কি (keys)-গুলোর ওপর লুপ চালিয়ে সম্পূর্ণ নতুন একটি টাইপ তৈরি করা যায়। [K in keyof T] সিনট্যাক্স ব্যবহার করে একটি মূল ইন্টারফেস থেকে তার নানা রকম ভ্যারিয়েশন তৈরি করা যায় (যেমন- সব প্রপার্টি অপশনাল বা রিড-অনলি করা), যার ফলে একই কোড বারবার লিখতে হয় না।
বিস্তারিত উত্তর:
ধরে নিন, আপনার কাছে ২০টি প্রপার্টিসহ একটি User ইন্টারফেস আছে। এখন আপডেট করার জন্য আপনার এমন একটি ইন্টারফেস প্রয়োজন যেখানে ওই ২০টি প্রপার্টিই অপশনাল থাকবে। ম্যানুয়ালি কপি-পেস্ট করে সবগুলোতে ? বসানো বেশ বিরক্তিকর এবং ভুলের সম্ভাবনা থাকে।
ম্যাপড টাইপস মূলত টাইপের জন্য একটি for...in লুপের মতো কাজ করে। এটি আগের টাইপের ওপর লুপ চালিয়ে নতুন নিয়ম অ্যাপ্লাই করে। টাইপস্ক্রিপ্টের বিল্ট-ইন ইউটিলিটি টাইপগুলো (যেমন Partial, Readonly) মূলত এই ম্যাপড টাইপসের কনসেপ্ট ব্যবহার করেই তৈরি।
Question 30: Explore Utility Types (Partial, Pick, Omit, etc.)
Short Answer:
Utility Types are globally available, built-in type transformers in TypeScript that help you manipulate existing types quickly. Instead of writing custom complex mapped types, you can use these shortcuts to make properties optional (Partial), extract specific keys (Pick), remove specific keys (Omit), or make everything immutable (Readonly).
Detailed Answer:
TypeScript provides a rich set of utility types to keep your code DRY. The most common ones include:
Partial<T>: Makes all properties of a type optional. Great for update/patch API payloads.Pick<T, Keys>: Extracts only the specified keys from a type to create a smaller type.Omit<T, Keys>: Does the opposite of Pick. It takes a type and removes the specified keys, useful for stripping out sensitive data like passwords.Readonly<T>: Prevents reassignment of the object's properties after initialization.
TypeScript
interface Product {
id: number;
name: string;
price: number;
description: string;
}// 1. Partial: All fields optional
type UpdateProduct = Partial<Product>;// 2. Pick: Only id and name
type ProductPreview = Pick<Product, "id" | "name">;// 3. Omit: Everything except description
type ProductWithoutDesc = Omit<Product, "description">;
প্রশ্ন ৩০: ইউটিলিটি টাইপস (Utility Types)
সংক্ষিপ্ত উত্তর:
ইউটিলিটি টাইপগুলো হলো টাইপস্ক্রিপ্টের কিছু বিল্ট-ইন বা আগে থেকে তৈরি করা টুল, যা দিয়ে খুব সহজেই বিদ্যমান টাইপকে পরিবর্তন করা যায়। কাস্টম ম্যাপড টাইপ লেখার ঝামেলা এড়িয়ে আপনি এগুলোর সাহায্যে খুব সহজেই প্রপার্টিগুলোকে অপশনাল করা (Partial), নির্দিষ্ট কিছু কি (key) বেছে নেওয়া (Pick), বাদ দেওয়া (Omit) বা রিড-অনলি (Readonly) করতে পারেন।
বিস্তারিত উত্তর:
কোড ক্লিন রাখার জন্য টাইপস্ক্রিপ্ট অনেকগুলো ইউটিলিটি টাইপ প্রদান করে। এর মধ্যে সবচেয়ে বেশি ব্যবহৃত হয়:
১. Partial<T>: এটি মূল টাইপের সব প্রপার্টিকে অপশনাল করে দেয়। আপডেট বা প্যাচ (patch) রিকোয়েস্টের ডেটার জন্য এটি দারুণ।
২. Pick<T, Keys>: একটি বড় টাইপ থেকে শুধুমাত্র প্রয়োজনীয় কয়েকটি প্রপার্টি তুলে নিয়ে ছোট টাইপ তৈরি করে।
৩. Omit<T, Keys>: এটি Pick এর ঠিক উল্টো। মূল টাইপ থেকে নির্দিষ্ট কোনো প্রপার্টি (যেমন- পাসওয়ার্ড) বাদ দিতে এটি ব্যবহৃত হয়।
৪. Readonly<T>: অবজেক্ট তৈরি হওয়ার পর এর ডেটা যেন আর পরিবর্তন করা না যায়, তা নিশ্চিত করে।
Question 31: Type Guard using typeof and in
Short Answer:
Type Guards are techniques used to narrow down a broad type (like a union) into a specific type within a conditional block. The typeof operator checks primitive types (string, number, boolean) at runtime, while the in operator checks if a specific property exists inside an object, allowing TypeScript to safely assume the object's exact type.
Detailed Answer:
When working with Union types, TypeScript restricts you to using only properties that are common to all types in the union. To bypass this, we use Type Guards.
typeofType Guard: Used exclusively for primitive values. If a variable isstring | number, wrapping logic insideif (typeof val === 'string')allows you to safely use string methods inside that block.inType Guard: Used for objects. If you have two different interfaces (e.g.,CarandBoat), you can checkif ('swim' in vehicle)to determine if the object is specifically aBoat.
TypeScript
// 1. typeof Type Guard
function formatID(id: string | number) {
if (typeof id === "string") {
return id.toUpperCase(); // TS knows id is a string here
}
return id.toFixed(2); // TS knows id is a number here
}// 2. in Type Guard
interface Bird { fly: () => void }
interface Fish { swim: () => void }function move(animal: Bird | Fish) {
if ("fly" in animal) {
animal.fly(); // Safely narrowed to Bird
} else {
animal.swim(); // Safely narrowed to Fish
}
}
প্রশ্ন ৩১: typeof এবং in ব্যবহার করে টাইপ গার্ড (Type Guard)
সংক্ষিপ্ত উত্তর:
টাইপ গার্ড হলো এমন একটি কৌশল যা কোনো একটি বড় টাইপকে (যেমন- ইউনিয়ন টাইপ) কন্ডিশন ব্লকের মাধ্যমে ছোট এবং নির্দিষ্ট টাইপে পরিণত করে। typeof অপারেটর দিয়ে প্রিমিটিভ ডেটার (স্ট্রিং, নাম্বার) টাইপ চেক করা হয়, আর in অপারেটর দিয়ে চেক করা হয় অবজেক্টের ভেতরে কোনো নির্দিষ্ট প্রপার্টি আছে কিনা। এর ফলে টাইপস্ক্রিপ্ট অবজেক্টটির সঠিক টাইপ ধরতে পারে।
বিস্তারিত উত্তর:
ইউনিয়ন টাইপ নিয়ে কাজ করার সময়, টাইপস্ক্রিপ্ট শুধু ওই প্রপার্টিগুলোই ব্যবহার করতে দেয় যেগুলো সব টাইপের মধ্যে কমন। এটি সমাধান করতেই টাইপ গার্ড ব্যবহৃত হয়।
১. typeof টাইপ গার্ড: এটি শুধুমাত্র প্রিমিটিভ ভ্যালুর ক্ষেত্রে ব্যবহৃত হয়। ভেরিয়েবলটি string | number হলে, if (typeof val === 'string') কন্ডিশনের ভেতরে টাইপস্ক্রিপ্ট আপনাকে স্ট্রিংয়ের সব মেথড ব্যবহার করতে দেবে।
২. in টাইপ গার্ড: এটি অবজেক্টের জন্য ব্যবহৃত হয়। দুটি আলাদা ইন্টারফেস (যেমন Car এবং Boat) থাকলে, if ('swim' in vehicle) চেক করার মাধ্যমে আপনি নিশ্চিত হতে পারেন যে অবজেক্টটি একটি Boat।
Question 32: Type Guard using instanceof
Short Answer:
The instanceof operator is a type guard specifically used for narrowing down objects that were instantiated from JavaScript/TypeScript Classes. While in checks for properties, instanceof checks the actual prototype chain at runtime to verify if an object is an instance of a specific class constructor.
Detailed Answer:
When dealing with Object-Oriented Programming (OOP) in TypeScript, you often pass around class instances instead of plain objects. If a function accepts a union of two different classes, you cannot use typeof (because both are objects).
Using instanceof allows you to explicitly check which class created the object. Once checked, TypeScript intelligently narrows the type, exposing the specific methods and properties of that class within the if block.
TypeScript
class Dog {
bark() { console.log("Woof!"); }
}class Cat {
meow() { console.log("Meow!"); }
}function handlePet(pet: Dog | Cat) {
if (pet instanceof Dog) {
pet.bark(); // TS narrows type to Dog
} else {
pet.meow(); // TS narrows type to Cat
}
}const myPet = new Dog();
handlePet(myPet); // Output: Woof!
প্রশ্ন ৩২: instanceof ব্যবহার করে টাইপ গার্ড (Type Guard)
সংক্ষিপ্ত উত্তর:
instanceof অপারেটরটি এমন একটি টাইপ গার্ড যা মূলত ক্লাস (Class) থেকে তৈরি হওয়া অবজেক্টগুলোর টাইপ নির্দিষ্ট করতে ব্যবহৃত হয়। in অপারেটর যেখানে প্রপার্টি চেক করে, সেখানে instanceof রানটাইমে প্রোটোটাইপ চেইন চেক করে নিশ্চিত হয় যে অবজেক্টটি নির্দিষ্ট কোনো ক্লাস থেকেই তৈরি হয়েছে কিনা।
বিস্তারিত উত্তর:
টাইপস্ক্রিপ্টে অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং (OOP) নিয়ে কাজ করার সময় আমরা সাধারণ অবজেক্টের বদলে ক্লাসের ইনস্ট্যান্স (instance) ব্যবহার করি। ফাংশনে যদি দুটি আলাদা ক্লাসের ইউনিয়ন পাস করা হয়, তবে typeof ব্যবহার করা যায় না (কারণ দুটোই অবজেক্ট)।
এক্ষেত্রে instanceof ব্যবহার করে আমরা চেক করতে পারি যে অবজেক্টটি ঠিক কোন ক্লাস থেকে তৈরি হয়েছে। একবার চেক করা হয়ে গেলে, টাইপস্ক্রিপ্ট স্মার্টলি টাইপটিকে নির্দিষ্ট করে দেয় এবং if ব্লকের ভেতরে ওই নির্দিষ্ট ক্লাসের মেথডগুলো অ্যাক্সেস করতে দেয়।
দুঃখিত যে ৩টি ফেজে শেষ করা হয়নি, তবে আমি আপনার সব টপিক নিখুঁতভাবে কভার করার জন্য একটু গুছিয়ে দিয়েছি। এখানে আপনার লিস্টের একদম শেষ অংশ, অর্থাৎ OOP (Object-Oriented Programming) এর কনসেপ্টগুলো নিয়ে Phase 5 দেওয়া হলো।
Medium-এ পাবলিশ করার জন্য এটি ঠিক আগের মতোই স্পেসিং এবং কোড এক্সাম্পল দিয়ে সাজানো হয়েছে।
Phase 5: Object-Oriented Programming (OOP) in TypeScript
Question 33: What is OOP and when do we use it? (With a real-life example)
Short Answer:
Object-Oriented Programming (OOP) is a programming paradigm centered around “objects”, which bundle related data (properties) and behaviors (methods) together. In TypeScript, OOP provides a highly structured and scalable way to build complex applications by organizing code into reusable blueprints (classes) rather than having scattered variables and isolated functions.
Detailed Answer:
Real-life Example: Think of a Banking System. Without OOP, you might have global variables like balance and independent functions like deposit() or withdraw(). If multiple users access the system, managing whose balance is updating becomes a chaotic mess.
With OOP, you create a blueprint (Class) called BankAccount. This blueprint defines that every account will have an accountHolderName, a balance, and its own deposit() method. When "John" and "Alice" join, you create separate Objects (instances) for them from this blueprint. John’s deposits securely update only John’s balance. We use OOP when our application deals with distinct entities (like Users, Products, Orders) that have their own states and behaviors.
প্রশ্ন ৩৩: OOP কী এবং আমরা এটি কখন ব্যবহার করি? (বাস্তব উদাহরণসহ)
সংক্ষিপ্ত উত্তর:
অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং (OOP) হলো প্রোগ্রামিংয়ের এমন একটি ধরন যা “অবজেক্ট” এর ওপর ভিত্তি করে কাজ করে, যেখানে সম্পর্কিত ডেটা (প্রপার্টি) এবং কাজগুলো (মেথড) একসাথে গুছিয়ে রাখা হয়। টাইপস্ক্রিপ্টে ছড়ানো-ছিটানো ভেরিয়েবল বা ফাংশন লেখার বদলে ক্লাস (Class) ব্যবহার করে একটি স্কেলেবল এবং গোছানো অ্যাপ্লিকেশন তৈরি করতে OOP ব্যবহার করা হয়।
বিস্তারিত উত্তর:
রিয়েল লাইফ এক্সাম্পল: একটি ব্যাংকিং সিস্টেমের কথা চিন্তা করুন। OOP ছাড়া আপনার কোডে হয়তো balance নামে একটি গ্লোবাল ভেরিয়েবল এবং deposit() নামে একটি সাধারণ ফাংশন থাকবে। একাধিক ইউজার আসলে কার ব্যালেন্স আপডেট হচ্ছে তা ট্র্যাক করা কঠিন হয়ে যাবে।
কিন্তু OOP ব্যবহার করলে আপনি BankAccount নামের একটি ব্লু-প্রিন্ট বা ক্লাস তৈরি করতে পারেন। এই ক্লাসে বলা থাকবে যে প্রতিটি অ্যাকাউন্টের একটি accountHolderName, balance এবং নিজস্ব deposit() মেথড থাকবে। যখন "John" এবং "Alice" যুক্ত হবে, তখন আপনি ওই ক্লাস থেকে তাদের জন্য আলাদা অবজেক্ট তৈরি করবেন। ফলে John এর অ্যাকাউন্টে টাকা জমা দিলে শুধু তার ব্যালেন্সই আপডেট হবে। অ্যাপ্লিকেশনে যখন আলাদা আলাদা এনটিটি (যেমন- User, Product, Order) নিয়ে কাজ করতে হয়, তখন আমরা OOP ব্যবহার করি।
Question 34: Understanding Class, Constructor, and Class to Object
Short Answer:
A Class acts as a template or blueprint for creating objects, defining the structural properties and methods they will possess. A Constructor is a special built-in initialization method inside the class that gets executed automatically the moment an object is created. "Class to Object" instantiation is the process of creating a real, usable entity in memory from that blueprint using the new keyword.
Detailed Answer:
The lifecycle of OOP starts with a Class.
- Class: The blueprint defining what data is needed.
- Constructor: When you create an object, you usually need to pass some initial data (like setting a user’s name). The constructor receives this data and assigns it to the class properties using the
thiskeyword. - Class to Object: You use the
newkeyword to tell the engine to allocate memory and create a fresh, independent object based on the class.
TypeScript
// 1. The Class
class User {
name: string;
age: number;// 2. The Constructor
constructor(userName: string, userAge: number) {
this.name = userName;
this.age = userAge;
}
}// 3. Class to Object (Instantiation)
const user1 = new User("Alice", 25);
console.log(user1.name); // "Alice"
প্রশ্ন ৩৪: Class, Constructor এবং Class থেকে Object তৈরি করার কনসেপ্ট
সংক্ষিপ্ত উত্তর:
Class হলো অবজেক্ট তৈরি করার একটি টেমপ্লেট বা ব্লু-প্রিন্ট, যা অবজেক্টের প্রপার্টি এবং মেথডগুলো নির্ধারণ করে। Constructor হলো ক্লাসের ভেতরের একটি বিশেষ মেথড, যা কোনো অবজেক্ট তৈরি হওয়ার সাথে সাথেই স্বয়ংক্রিয়ভাবে এক্সিকিউট হয়। new কি-ওয়ার্ড ব্যবহার করে ক্লাস নামের নকশা থেকে মেমরিতে একটি বাস্তব অবজেক্ট তৈরি করার প্রক্রিয়াকেই "Class to Object" বা ইন্সট্যান্সিয়েশন বলা হয়।
বিস্তারিত উত্তর:
OOP এর জীবনচক্র মূলত ক্লাস দিয়েই শুরু হয়।
১. Class: এটি একটি নকশা যা ঠিক করে দেয় কী কী ডেটা থাকবে।
২. Constructor: অবজেক্ট তৈরি করার সময় কিছু প্রাথমিক ডেটা (যেমন- ইউজারের নাম) পাস করতে হয়। কনস্ট্রাক্টর সেই ডেটা রিসিভ করে এবং this কি-ওয়ার্ড ব্যবহার করে ক্লাসের প্রপার্টিতে সেট করে দেয়।
৩. Class to Object: new কি-ওয়ার্ড ব্যবহার করে আমরা ইঞ্জিনকে নির্দেশ দিই যেন সে ওই ক্লাসের ওপর ভিত্তি করে একটি সম্পূর্ণ নতুন অবজেক্ট তৈরি করে।
Question 35: Encapsulation & Access Modifiers (Public, Private, Protected)
Short Answer:
Encapsulation (the 4th pillar of OOP) is the practice of bundling data and hiding the internal state of an object from the outside world to prevent unauthorized changes. TypeScript enforces this using Access Modifiers: public (accessible from anywhere), private (accessible only within the class itself), and protected (accessible within the class and its subclasses).
Detailed Answer:
In pure JavaScript, everything inside a class is public by default, which can lead to accidental data modification. TypeScript fixes this natively.
- public: The default modifier. Data can be read and changed from outside the class.
- private: Strict privacy. The property cannot be accessed directly from the object instance (
user.balancewill throw an error). It secures sensitive data. - protected: Similar to private, but allows child classes (derived via inheritance) to access the property.
TypeScript
class BankAccount {
public accountName: string; // Accessible anywhere
private balance: number; // Encapsulated (Hidden)
protected bankCode: string; // Hidden, but accessible in child classesconstructor(name: string, initialBalance: number) {
this.accountName = name;
this.balance = initialBalance;
this.bankCode = "BD-101";
}
}const myAccount = new BankAccount("John", 5000);
console.log(myAccount.accountName); // Valid
// console.log(myAccount.balance); // Error: Property 'balance' is private
প্রশ্ন ৩৫: এনক্যাপসুলেশন এবং অ্যাক্সেস মডিফায়ার (Public, Private, Protected)
সংক্ষিপ্ত উত্তর:
এনক্যাপসুলেশন (OOP এর চতুর্থ পিল্যার) হলো অবজেক্টের ভেতরের গুরুত্বপূর্ণ ডেটাকে বাইরের জগৎ থেকে লুকিয়ে রাখার একটি পদ্ধতি, যাতে কেউ ভুলবশত ডেটা পরিবর্তন করতে না পারে। টাইপস্ক্রিপ্টে এটি ৩টি অ্যাক্সেস মডিফায়ার দিয়ে নিয়ন্ত্রণ করা হয়: public (যেকোনো জায়গা থেকে অ্যাক্সেসযোগ্য), private (শুধুমাত্র নিজের ক্লাসের ভেতর ব্যবহারযোগ্য), এবং protected (নিজের ক্লাস এবং ইনহেরিট করা চাইল্ড ক্লাসের ভেতর ব্যবহারযোগ্য)।
বিস্তারিত উত্তর:
সাধারণ জাভাস্ক্রিপ্টে ক্লাসের সবকিছুই ডিফল্টভাবে পাবলিক থাকে, যার ফলে অনাকাঙ্ক্ষিত ডেটা পরিবর্তনের ঝুঁকি থাকে। টাইপস্ক্রিপ্ট এটি সমাধান করেছে।
- public: এটি ডিফল্ট। ক্লাসের বাইরে থেকে ডেটা পড়া বা পরিবর্তন করা যায়।
- private: সম্পূর্ণ প্রাইভেসি। অবজেক্ট থেকে সরাসরি এই ডেটা কল করা যায় না (যেমন-
user.balanceলিখলে এরর আসবে)। এটি ডেটাকে সুরক্ষিত রাখে। - protected: এটি প্রাইভেটের মতোই, তবে পার্থক্য হলো ইনহেরিট করে তৈরি করা চাইল্ড ক্লাসগুলো এই প্রপার্টি অ্যাক্সেস করতে পারে।
Question 36: Getter and Setter in TypeScript
Short Answer:
Getters and Setters are special methods used to securely read (get) and modify (set) the private properties of a class. They act as a controlled gateway, allowing developers to add validation logic, format data, or compute values dynamically before exposing or changing the internal state of an object.
Detailed Answer:
Since Encapsulation forces us to make sensitive properties private, we need a safe way to interact with them.
Using the get keyword, you can return a private value (perhaps modifying it slightly, like adding currency symbols). Using the set keyword, you can apply validation before saving the new value. The beautiful part is that when you use the object, getters and setters look and behave exactly like normal properties, not functions.
TypeScript
class Product {
private _price: number = 0;// Getter
get price(): number {
return this._price;
} // Setter with validation
set price(newPrice: number) {
if (newPrice < 0) {
throw new Error("Price cannot be negative!");
}
this._price = newPrice;
}
}const item = new Product();
item.price = 500; // Calls the Setter
console.log(item.price); // Calls the Getter. Output: 500
// item.price = -10; // Throws Error
প্রশ্ন ৩৬: টাইপস্ক্রিপ্টে গেটার (Getter) এবং সেটার (Setter)
সংক্ষিপ্ত উত্তর:
গেটার এবং সেটার হলো ক্লাসের ভেতরের প্রাইভেট প্রপার্টিগুলোকে সুরক্ষিতভাবে পড়ার (get) এবং পরিবর্তন করার (set) জন্য ব্যবহৃত বিশেষ মেথড। এগুলোর মাধ্যমে ডেভেলপাররা ডেটা আপডেট করা বা প্রকাশ করার আগে কন্ডিশন বা ভ্যালিডেশন চেক করতে পারেন, যা এনক্যাপসুলেশনকে আরও শক্তিশালী করে।
বিস্তারিত উত্তর:
যেহেতু এনক্যাপসুলেশনের কারণে আমরা প্রপার্টিগুলোকে private করে রাখি, তাই সেগুলোর সাথে কাজ করার জন্য একটি নিরাপদ মাধ্যম প্রয়োজন।
get কি-ওয়ার্ড ব্যবহার করে আপনি প্রাইভেট ভ্যালু রিটার্ন করতে পারেন। আর set কি-ওয়ার্ড ব্যবহার করে নতুন ভ্যালু সেভ করার আগে কন্ডিশন চেক (যেমন- দাম মাইনাস হবে না) করতে পারেন। এর সবচেয়ে সুন্দর দিক হলো, অবজেক্ট ব্যবহারের সময় এগুলোকে মেথডের মতো কল করতে হয় না, সাধারণ প্রপার্টির মতোই ব্যবহার করা যায়।
Question 37: Statics in TypeScript
Short Answer:
The static keyword is used to define properties or methods that belong to the Class itself, rather than to the individual instances (objects) created from that class. This means you can call a static method directly on the class name without ever needing to use the new keyword to create an object first.
Detailed Answer:
Static members share the same memory space across the entire application. They are heavily used for utility functions, configuration constants, or tracking global states across all instances. For example, JavaScript’s built-in Math.PI or Math.random() are static properties/methods because you don't do new Math() to use them.
TypeScript
class MathUtility {
// Static property
static PI: number = 3.1416;// Static method
static calculateArea(radius: number): number {
return this.PI * radius * radius;
}
}// Accessing directly via the Class name, no 'new' required!
console.log(MathUtility.PI);
console.log(MathUtility.calculateArea(5));
প্রশ্ন ৩৭: টাইপস্ক্রিপ্টে স্ট্যাটিকস (Statics)
সংক্ষিপ্ত উত্তর:
static কি-ওয়ার্ড ব্যবহার করে এমন প্রপার্টি বা মেথড তৈরি করা হয় যা নির্দিষ্ট কোনো অবজেক্টের ওপর নির্ভর করে না, বরং সরাসরি ক্লাসের নিজস্ব প্রপার্টি হিসেবে কাজ করে। এর মানে হলো, স্ট্যাটিক মেথড ব্যবহার করার জন্য new কি-ওয়ার্ড দিয়ে আগে কোনো অবজেক্ট বানানোর প্রয়োজন হয় না; সরাসরি ক্লাসের নাম ধরেই তাকে কল করা যায়।
বিস্তারিত উত্তর:
স্ট্যাটিক মেম্বারগুলো পুরো অ্যাপ্লিকেশনে একই মেমরি শেয়ার করে। ইউটিলিটি ফাংশন, গ্লোবাল কনফিগারেশন বা কতগুলো অবজেক্ট তৈরি হলো তা ট্র্যাক করতে এটি খুব ব্যবহার করা হয়। উদাহরণস্বরূপ, জাভাস্ক্রিপ্টের Math.PI বা Math.random() হলো স্ট্যাটিক প্রপার্টি/মেথড, কারণ এগুলো ব্যবহার করতে আমাদের new Math() তৈরি করতে হয় না।
Question 38: Inheritance (The 1st Pillar of OOP)
Short Answer:
Inheritance is an OOP mechanism where one class (the Child or Subclass) derives the properties and methods of another class (the Parent or Superclass) using the extends keyword. It promotes the DRY (Don't Repeat Yourself) principle by allowing the child class to reuse the parent's logic while having the flexibility to add its own specific features.
Detailed Answer:
When building complex systems, multiple classes often share common features. Instead of writing the same code in every class, you put the shared logic in a Parent class.
If a child class has its own constructor, it must call super() before doing anything else. super() executes the parent class's constructor, ensuring the inherited properties are initialized properly.
TypeScript
// Parent Class
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
eat() {
console.log(`${this.name} is eating.`);
}
}// Child Class inheriting from Animal
class Dog extends Animal {
breed: string;
constructor(name: string, breed: string) {
super(name); // Calls the Animal constructor
this.breed = breed;
}
}const myDog = new Dog("Buddy", "Golden Retriever");
myDog.eat(); // Reusing the parent's method: "Buddy is eating."
প্রশ্ন ৩৮: ইনহেরিটেন্স (Inheritance — OOP এর ১ম পিল্যার)
সংক্ষিপ্ত উত্তর:
ইনহেরিটেন্স হলো OOP এর এমন একটি মেকানিজম যেখানে একটি ক্লাস (চাইল্ড ক্লাস) extends কি-ওয়ার্ড ব্যবহার করে অন্য একটি ক্লাসের (প্যারেন্ট ক্লাস) প্রপার্টি এবং মেথড উত্তরাধিকারসূত্রে লাভ করে। এটি কোড রিপিটেশন কমায়। চাইল্ড ক্লাস চাইলেই প্যারেন্টের কোড ব্যবহার করতে পারে এবং পাশাপাশি নিজের জন্য নতুন ফিচারও যুক্ত করতে পারে।
বিস্তারিত উত্তর:
বড় সিস্টেমে একাধিক ক্লাসের মধ্যে অনেক কমন ফিচার থাকে। সব ক্লাসে বারবার একই কোড না লিখে আমরা কমন কোডগুলো একটি প্যারেন্ট ক্লাসে রাখি।
চাইল্ড ক্লাসে যদি নিজস্ব constructor থাকে, তবে সেখানে সবার আগে super() কল করতে হয়। super() মূলত প্যারেন্ট ক্লাসের কনস্ট্রাক্টরকে রান করে, যাতে প্যারেন্ট ক্লাসের প্রপার্টিগুলো ঠিকঠাক সেট হয়ে যায়।
Question 39: Polymorphism (The 2nd Pillar of OOP)
Short Answer:
Polymorphism translates to “many forms.” In OOP, it allows methods to do different things based on the object it is acting upon, even though the method shares the exact same name. In TypeScript, this is primarily achieved through “Method Overriding”, where a child class provides its own specific implementation of a method already defined in its parent class.
Detailed Answer:
Polymorphism ensures that the system is flexible. If you have a parent class Animal with a method makeSound(), different animals shouldn't make the exact same sound. The Dog class overrides makeSound() to say "Woof", and the Cat class overrides it to say "Meow". The function name remains the same, but the behavior changes based on the object calling it.
TypeScript
class Animal {
makeSound() {
console.log("Some generic animal sound...");
}
}class Dog extends Animal {
// Overriding the parent's method
makeSound() {
console.log("Woof! Woof!");
}
}class Cat extends Animal {
// Overriding the parent's method
makeSound() {
console.log("Meow!");
}
}const myDog = new Dog();
myDog.makeSound(); // Outputs: Woof! Woof!
প্রশ্ন ৩৯: পলিমরফিজম (Polymorphism — OOP এর ২য় পিল্যার)
সংক্ষিপ্ত উত্তর:
পলিমরফিজম মানে হলো “বহুরূপিতা”। OOP-তে এর মানে হলো, একই নামের মেথড ভিন্ন ভিন্ন অবজেক্টের ক্ষেত্রে ভিন্ন ভিন্ন আচরণ করবে। টাইপস্ক্রিপ্টে এটি মূলত “মেথড ওভাররাইডিং (Method Overriding)” এর মাধ্যমে করা হয়, যেখানে চাইল্ড ক্লাস তার প্যারেন্ট ক্লাসে থাকা মেথডটিকে নিজের মতো করে কাস্টমাইজ করে নেয়।
বিস্তারিত উত্তর:
পলিমরফিজম সিস্টেমকে অনেক ফ্লেক্সিবল করে। ধরুন আপনার Animal নামের প্যারেন্ট ক্লাসে makeSound() নামের একটি মেথড আছে। কিন্তু সব প্রাণী তো আর একই শব্দ করে না! তাই Dog ক্লাস makeSound()-কে ওভাররাইড করে "ঘেউ ঘেউ" প্রিন্ট করতে পারে, আবার Cat ক্লাস "মিউ" প্রিন্ট করতে পারে। মেথডের নাম একই থাকে, কিন্তু যে অবজেক্ট তাকে কল করছে তার ওপর ভিত্তি করে কাজের ধরন বদলে যায়।
Question 40: Abstraction (The 3rd Pillar of OOP)
Short Answer:
Abstraction is the concept of hiding the complex background implementation details of a system and exposing only the essential features to the user. In TypeScript, this is enforced using the abstract keyword on classes and methods. An abstract class serves as a strict, high-level template that cannot be instantiated directly but must be inherited and implemented by derived child classes.
Detailed Answer:
When you drive a car, you only interact with the steering wheel and pedals. You don’t need to know the complex combustion logic inside the engine. That is abstraction.
In code, an abstract class provides the shape of what must be done, but leaves the how to the child classes. If a class contains an abstract method, it forces the inheriting child class to provide the actual code for that method.
TypeScript
// Abstract Class (Template)
abstract class Shape {
// Abstract method: No body, just the signature
abstract getArea(): number; // Regular method is allowed too
printInfo() {
console.log("I am a shape.");
}
}// const s = new Shape(); // Error: Cannot create an instance of an abstract class.class Circle extends Shape {
radius: number;
constructor(radius: number) {
super();
this.radius = radius;
} // MUST implement the abstract method
getArea(): number {
return Math.PI * this.radius * this.radius;
}
}const myCircle = new Circle(5);
console.log(myCircle.getArea());
প্রশ্ন ৪০: অ্যাবস্ট্রাকশন (Abstraction — OOP এর ৩য় পিল্যার)
সংক্ষিপ্ত উত্তর:
অ্যাবস্ট্রাকশন হলো কোনো সিস্টেমের পেছনের জটিল লজিক বা কার্যকলাপগুলো লুকিয়ে রেখে শুধুমাত্র দরকারি জিনিসগুলো ব্যবহারকারীর সামনে তুলে ধরার প্রক্রিয়া। টাইপস্ক্রিপ্টে ক্লাস এবং মেথডের আগে abstract কি-ওয়ার্ড ব্যবহার করে এটি করা হয়। একটি অ্যাবস্ট্রাক্ট ক্লাস একটি কড়া টেমপ্লেট হিসেবে কাজ করে, যার থেকে সরাসরি কোনো অবজেক্ট তৈরি করা যায় না, চাইল্ড ক্লাসকে অবশ্যই একে ইনহেরিট করে কাজগুলো সম্পন্ন করতে হয়।
বিস্তারিত উত্তর:
আপনি যখন গাড়ি চালান, তখন আপনি শুধু স্টিয়ারিং আর প্যাডেল ব্যবহার করেন। ইঞ্জিনের ভেতরে কীভাবে কাজ হচ্ছে তা আপনার জানার প্রয়োজন নেই। এটিই অ্যাবস্ট্রাকশন।
কোডিংয়ের ক্ষেত্রে, একটি abstract ক্লাস শুধু বলে দেয় "কী কাজ করতে হবে", কিন্তু "কীভাবে করতে হবে" তা চাইল্ড ক্লাসের ওপর ছেড়ে দেয়। কোনো ক্লাসে যদি অ্যাবস্ট্রাক্ট মেথড থাকে, তবে ইনহেরিট করা চাইল্ড ক্লাসটিকে অবশ্যই ওই মেথডের আসল কোড লিখতে বাধ্য থাকতে হয়।



