বাংলা

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

টাইপস্ক্রিপ্ট এক্সেস প্রপার্টি চেকস: আপনার অবজেক্ট টাইপ সুরক্ষাকে শক্তিশালী করুন

আধুনিক সফটওয়্যার ডেভেলপমেন্টের জগতে, বিশেষ করে জাভাস্ক্রিপ্টের ক্ষেত্রে, আপনার কোডের অখণ্ডতা এবং নির্ভরযোগ্যতা নিশ্চিত করা অত্যন্ত গুরুত্বপূর্ণ। যদিও জাভাস্ক্রিপ্ট অসাধারণ নমনীয়তা প্রদান করে, তবে এটি কখনও কখনও অপ্রত্যাশিত ডেটা স্ট্রাকচার বা প্রপার্টি গরমিলের কারণে রানটাইম এররের কারণ হতে পারে। এখানেই টাইপস্ক্রিপ্ট তার অসাধারণত্ব দেখায়, যা স্ট্যাটিক টাইপিং ক্ষমতা প্রদান করে এবং অনেক সাধারণ ভুল প্রোডাকশনে যাওয়ার আগেই ধরে ফেলে। টাইপস্ক্রিপ্টের অন্যতম শক্তিশালী অথচ কখনও কখনও ভুল বোঝা একটি ফিচার হলো এর এক্সেস প্রপার্টি চেক (excess property check)

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

মূল ধারণা বোঝা: এক্সেস প্রপার্টি চেক কী?

মূলত, টাইপস্ক্রিপ্টের এক্সেস প্রপার্টি চেক হলো একটি কম্পাইলার প্রক্রিয়া যা আপনাকে এমন একটি অবজেক্ট লিটারেলকে ভেরিয়েবলে অ্যাসাইন করতে বাধা দেয়, যার টাইপ সেই অতিরিক্ত প্রপার্টিগুলোকে স্পষ্টভাবে অনুমোদন করে না। সহজ ভাষায়, যদি আপনি একটি অবজেক্ট লিটারেল সংজ্ঞায়িত করেন এবং এটিকে একটি নির্দিষ্ট টাইপ ডেফিনিশন (যেমন ইন্টারফেস বা টাইপ অ্যালিয়াস) সহ একটি ভেরিয়েবলে অ্যাসাইন করার চেষ্টা করেন এবং সেই লিটারেলে সংজ্ঞায়িত টাইপে ঘোষণা করা হয়নি এমন প্রপার্টি থাকে, তবে টাইপস্ক্রিপ্ট কম্পাইলেশনের সময় এটিকে একটি এরর হিসেবে চিহ্নিত করবে।

আসুন একটি সাধারণ উদাহরণ দিয়ে বিষয়টি পরিষ্কার করা যাক:


interface User {
  name: string;
  age: number;
}

const newUser: User = {
  name: 'Alice',
  age: 30,
  email: 'alice@example.com' // এরর: অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'email' প্রপার্টিটি 'User' টাইপে বিদ্যমান নেই।
};

এই অংশে, আমরা `User` নামে একটি `interface` সংজ্ঞায়িত করেছি যার দুটি প্রপার্টি রয়েছে: `name` এবং `age`। যখন আমরা `email` নামে একটি অতিরিক্ত প্রপার্টিসহ একটি অবজেক্ট লিটারেল তৈরি করার চেষ্টা করি এবং এটিকে `User` টাইপের একটি ভেরিয়েবলে অ্যাসাইন করি, তখন টাইপস্ক্রিপ্ট সঙ্গে সঙ্গে এই গরমিলটি শনাক্ত করে। `email` প্রপার্টিটি একটি 'এক্সেস' বা 'অতিরিক্ত' প্রপার্টি কারণ এটি `User` ইন্টারফেসে সংজ্ঞায়িত নয়। এই চেকটি বিশেষভাবে তখনই করা হয় যখন আপনি অ্যাসাইনমেন্টের জন্য একটি অবজেক্ট লিটারেল ব্যবহার করেন।

এক্সেস প্রপার্টি চেক কেন গুরুত্বপূর্ণ?

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

কখন এক্সেস প্রপার্টি চেক প্রযোজ্য হয়?

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

দৃশ্যকল্প ১: ভেরিয়েবলে অবজেক্ট লিটারেল অ্যাসাইন করা

উপরে `User` উদাহরণে যেমন দেখা গেছে, অতিরিক্ত প্রপার্টিসহ একটি অবজেক্ট লিটারেলকে সরাসরি একটি টাইপড ভেরিয়েবলে অ্যাসাইন করা হলে এই চেকটি ট্রিগার হয়।

দৃশ্যকল্প ২: ফাংশনে অবজেক্ট লিটারেল পাস করা

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


interface Product {
  id: number;
  name: string;
}

function displayProduct(product: Product): void {
  console.log(`Product ID: ${product.id}, Name: ${product.name}`);
}

displayProduct({
  id: 101,
  name: 'Laptop',
  price: 1200 // এরর: '{ id: number; name: string; price: number; }' টাইপের আর্গুমেন্ট 'Product' টাইপের প্যারামিটারে অ্যাসাইন করা যাবে না।
             // অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'price' প্রপার্টিটি 'Product' টাইপে বিদ্যমান নেই।
});

এখানে, `displayProduct` ফাংশনে পাস করা অবজেক্ট লিটারেলের `price` প্রপার্টিটি একটি এক্সেস প্রপার্টি, কারণ `Product` ইন্টারফেস এটি সংজ্ঞায়িত করে না।

কখন এক্সেস প্রপার্টি চেক *না* প্রযোজ্য হয়?

বিভ্রান্তি এড়াতে এবং কখন বিকল্প কৌশল প্রয়োজন হতে পারে তা জানতে এই চেকগুলো কখন এড়িয়ে যাওয়া হয় তা বোঝাও সমান গুরুত্বপূর্ণ।

১. অ্যাসাইনমেন্টের জন্য অবজেক্ট লিটারেল ব্যবহার না করা হলে

যদি আপনি এমন একটি অবজেক্ট অ্যাসাইন করেন যা একটি অবজেক্ট লিটারেল নয় (যেমন, একটি ভেরিয়েবল যা ইতিমধ্যে একটি অবজেক্ট ধারণ করে), তবে এক্সেস প্রপার্টি চেক সাধারণত এড়িয়ে যাওয়া হয়।


interface Config {
  timeout: number;
}

function setupConfig(config: Config) {
  console.log(`Timeout set to: ${config.timeout}`);
}

const userProvidedConfig = {
  timeout: 5000,
  retries: 3 // এই 'retries' প্রপার্টিটি 'Config' অনুযায়ী একটি এক্সেস প্রপার্টি
};

setupConfig(userProvidedConfig); // কোনো এরর নেই!

// যদিও userProvidedConfig-এ একটি অতিরিক্ত প্রপার্টি রয়েছে, চেকটি এড়িয়ে যাওয়া হয়েছে
// কারণ এটি সরাসরি পাস করা কোনো অবজেক্ট লিটারেল নয়।
// টাইপস্ক্রিপ্ট userProvidedConfig-এর টাইপ পরীক্ষা করে।
// যদি userProvidedConfig-কে Config টাইপ দিয়ে ঘোষণা করা হতো, তবে আগেই একটি এরর ঘটত।
// তবে, যদি 'any' বা একটি বিস্তৃত টাইপ হিসেবে ঘোষণা করা হয়, তবে এররটি স্থগিত থাকে।

// বাইপাস দেখানোর একটি আরও সুনির্দিষ্ট উপায়:
let anotherConfig;

if (Math.random() > 0.5) {
  anotherConfig = {
    timeout: 1000,
    host: 'localhost' // এক্সেস প্রপার্টি
  };
} else {
  anotherConfig = {
    timeout: 2000,
    port: 8080 // এক্সেস প্রপার্টি
  };
}

setupConfig(anotherConfig as Config); // টাইপ অ্যাসারশন এবং বাইপাসের কারণে কোনো এরর নেই

// মূল বিষয় হলো, 'anotherConfig' setupConfig-এ অ্যাসাইনমেন্টের সময় একটি অবজেক্ট লিটারেল নয়।
// যদি আমাদের 'Config' হিসেবে টাইপ করা একটি মধ্যবর্তী ভেরিয়েবল থাকত, তবে প্রাথমিক অ্যাসাইনমেন্টটি ব্যর্থ হতো।

// মধ্যবর্তী ভেরিয়েবলের উদাহরণ:
let intermediateConfig: Config;

intermediateConfig = {
  timeout: 3000,
  logging: true // এরর: অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'logging' প্রপার্টিটি 'Config' টাইপে বিদ্যমান নেই।
};

প্রথম `setupConfig(userProvidedConfig)` উদাহরণে, `userProvidedConfig` একটি ভেরিয়েবল যা একটি অবজেক্ট ধারণ করে। টাইপস্ক্রিপ্ট পরীক্ষা করে যে `userProvidedConfig` সামগ্রিকভাবে `Config` টাইপের সাথে সঙ্গতিপূর্ণ কিনা। এটি `userProvidedConfig`-এর উপর কঠোর অবজেক্ট লিটারেল চেক প্রয়োগ করে না। যদি `userProvidedConfig`-কে এমন একটি টাইপ দিয়ে ঘোষণা করা হতো যা `Config`-এর সাথে মেলে না, তবে তার ঘোষণা বা অ্যাসাইনমেন্টের সময় একটি এরর ঘটত। বাইপাস ঘটে কারণ অবজেক্টটি ফাংশনে পাস করার আগে তৈরি এবং একটি ভেরিয়েবলে অ্যাসাইন করা হয়ে গেছে।

২. টাইপ অ্যাসারশন

আপনি টাইপ অ্যাসারশন ব্যবহার করে এক্সেস প্রপার্টি চেক এড়িয়ে যেতে পারেন, যদিও এটি সতর্কতার সাথে করা উচিত কারণ এটি টাইপস্ক্রিপ্টের সুরক্ষা গ্যারান্টিকে অগ্রাহ্য করে।


interface Settings {
  theme: 'dark' | 'light';
}

const mySettings = {
  theme: 'dark',
  fontSize: 14 // এক্সেস প্রপার্টি
} as Settings;

// এখানে টাইপ অ্যাসারশনের কারণে কোনো এরর নেই।
// আমরা টাইপস্ক্রিপ্টকে বলছি: "আমাকে বিশ্বাস করুন, এই অবজেক্টটি Settings-এর সাথে সঙ্গতিপূর্ণ।"
console.log(mySettings.theme);
// console.log(mySettings.fontSize); // যদি fontSize আসলে সেখানে না থাকত তবে এটি একটি রানটাইম এরর ঘটাত।

৩. টাইপ ডেফিনিশনে ইনডেক্স সিগনেচার বা স্প্রেড সিনট্যাক্স ব্যবহার করা

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

ইনডেক্স সিগনেচার ব্যবহার করে:


interface FlexibleObject {
  id: number;
  [key: string]: any; // যেকোনো মানের সাথে যেকোনো স্ট্রিং কী অনুমোদন করে
}

const flexibleItem: FlexibleObject = {
  id: 1,
  name: 'Widget',
  version: '1.0.0'
};

// কোনো এরর নেই কারণ 'name' এবং 'version' ইনডেক্স সিগনেচার দ্বারা অনুমোদিত।
console.log(flexibleItem.name);

টাইপ ডেফিনিশনে স্প্রেড সিনট্যাক্স ব্যবহার করে (সরাসরি চেক এড়ানোর জন্য কম ব্যবহৃত, সামঞ্জস্যপূর্ণ টাইপ সংজ্ঞায়িত করার জন্য বেশি):

যদিও এটি সরাসরি একটি বাইপাস নয়, স্প্রেডিং বিদ্যমান প্রপার্টি অন্তর্ভুক্ত করে নতুন অবজেক্ট তৈরি করতে দেয় এবং চেকটি গঠিত নতুন লিটারেলের উপর প্রযোজ্য হয়।

৪. `Object.assign()` বা স্প্রেড সিনট্যাক্স ব্যবহার করে মার্জ করা

যখন আপনি অবজেক্ট মার্জ করার জন্য `Object.assign()` বা স্প্রেড সিনট্যাক্স (`...`) ব্যবহার করেন, তখন এক্সেস প্রপার্টি চেক ভিন্নভাবে আচরণ করে। এটি গঠিত হওয়া নতুন অবজেক্ট লিটারেলের উপর প্রযোজ্য হয়।


interface BaseConfig {
  host: string;
}

interface ExtendedConfig extends BaseConfig {
  port: number;
}

const defaultConfig: BaseConfig = {
  host: 'localhost'
};

const userConfig = {
  port: 8080,
  timeout: 5000 // BaseConfig-এর তুলনায় এক্সেস প্রপার্টি, কিন্তু মার্জড টাইপ দ্বারা প্রত্যাশিত
};

// ExtendedConfig-এর সাথে সঙ্গতিপূর্ণ একটি নতুন অবজেক্ট লিটারেলে স্প্রেড করা হচ্ছে
const finalConfig: ExtendedConfig = {
  ...defaultConfig,
  ...userConfig
};

// এটি সাধারণত ঠিক আছে কারণ 'finalConfig'-কে 'ExtendedConfig' হিসেবে ঘোষণা করা হয়েছে
// এবং প্রপার্টিগুলো মিলে যায়। চেকটি 'finalConfig'-এর টাইপের উপর করা হয়।

// আসুন একটি পরিস্থিতি বিবেচনা করি যেখানে এটি ব্যর্থ হবে:

interface SmallConfig {
  key: string;
}

const data1 = { key: 'abc', value: 123 }; // এখানে 'value' অতিরিক্ত
const data2 = { key: 'xyz', status: 'active' }; // এখানে 'status' অতিরিক্ত

// এমন একটি টাইপে অ্যাসাইন করার চেষ্টা করা হচ্ছে যা অতিরিক্ত প্রপার্টি সমর্থন করে না

// const combined: SmallConfig = {
//   ...data1, // এরর: অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'value' প্রপার্টিটি 'SmallConfig' টাইপে বিদ্যমান নেই।
//   ...data2  // এরর: অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'status' প্রপার্টিটি 'SmallConfig' টাইপে বিদ্যমান নেই।
// };

// এররটি ঘটে কারণ স্প্রেড সিনট্যাক্স দ্বারা গঠিত অবজেক্ট লিটারেলটিতে
// 'SmallConfig'-এ উপস্থিত নেই এমন প্রপার্টি ('value', 'status') রয়েছে।

// যদি আমরা একটি বিস্তৃত টাইপ সহ একটি মধ্যবর্তী ভেরিয়েবল তৈরি করি:

const temp: any = {
  ...data1,
  ...data2
};

// তারপর SmallConfig-এ অ্যাসাইন করলে, প্রাথমিক লিটারেল তৈরির সময় এক্সেস প্রপার্টি চেক এড়িয়ে যাওয়া হয়,
// কিন্তু অ্যাসাইনমেন্টের উপর টাইপ চেকটি এখনও ঘটতে পারে যদি temp-এর টাইপ আরও কঠোরভাবে অনুমান করা হয়।
// তবে, যদি temp 'any' হয়, তবে 'combined'-এ অ্যাসাইনমেন্ট পর্যন্ত কোনো চেক হয় না।

// আসুন স্প্রেডের সাথে এক্সেস প্রপার্টি চেকের ধারণাটি পরিমার্জন করি:
// চেকটি ঘটে যখন স্প্রেড সিনট্যাক্স দ্বারা তৈরি অবজেক্ট লিটারেলটি
// একটি ভেরিয়েবলে অ্যাসাইন করা হয় বা একটি ফাংশনে পাস করা হয় যা আরও নির্দিষ্ট টাইপ আশা করে।

interface SpecificShape { 
  id: number;
}

const objA = { id: 1, extra1: 'hello' };
const objB = { id: 2, extra2: 'world' };

// এটি ব্যর্থ হবে যদি SpecificShape 'extra1' বা 'extra2' অনুমোদন না করে:
// const merged: SpecificShape = {
//   ...objA,
//   ...objB
// };

// এটি ব্যর্থ হওয়ার কারণ হলো স্প্রেড সিনট্যাক্স কার্যকরভাবে একটি নতুন অবজেক্ট লিটারেল তৈরি করে।
// যদি objA এবং objB-এর ওভারল্যাপিং কী থাকত, তবে পরেরটি জিতত। কম্পাইলার
// এই ফলস্বরূপ লিটারেলটি দেখে এবং এটিকে 'SpecificShape'-এর বিপরীতে পরীক্ষা করে।

// এটিকে কাজ করানোর জন্য, আপনার একটি মধ্যবর্তী পদক্ষেপ বা আরও অনুমতিমূলক টাইপের প্রয়োজন হতে পারে:

const tempObj = {
  ...objA,
  ...objB
};

// এখন, যদি tempObj-এর SpecificShape-এ নেই এমন প্রপার্টি থাকে, তবে অ্যাসাইনমেন্টটি ব্যর্থ হবে:
// const mergedCorrected: SpecificShape = tempObj; // এরর: অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে...

// মূল বিষয় হলো কম্পাইলার গঠিত হওয়া অবজেক্ট লিটারেলের আকার বিশ্লেষণ করে।
// যদি সেই লিটারেলে টার্গেট টাইপে সংজ্ঞায়িত নয় এমন প্রপার্টি থাকে, তবে এটি একটি এরর।

// এক্সেস প্রপার্টি চেকসহ স্প্রেড সিনট্যাক্সের সাধারণ ব্যবহার:

interface UserProfile {
  userId: string;
  username: string;
}

interface AdminProfile extends UserProfile {
  adminLevel: number;
}

const baseUserData: UserProfile = {
  userId: 'user-123',
  username: 'coder'
};

const adminData = {
  adminLevel: 5,
  lastLogin: '2023-10-27'
};

// এখানেই এক্সেস প্রপার্টি চেক প্রাসঙ্গিক:
// const adminProfile: AdminProfile = {
//   ...baseUserData,
//   ...adminData // এরর: অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'lastLogin' প্রপার্টিটি 'AdminProfile' টাইপে বিদ্যমান নেই।
// };

// স্প্রেড দ্বারা তৈরি অবজেক্ট লিটারেলে 'lastLogin' আছে, যা 'AdminProfile'-এ নেই।
// এটি ঠিক করতে, 'adminData'-কে আদর্শভাবে AdminProfile-এর সাথে সঙ্গতিপূর্ণ হতে হবে বা এক্সেস প্রপার্টিটি হ্যান্ডেল করা উচিত।

// সংশোধিত পদ্ধতি:
const validAdminData = {
  adminLevel: 5
};

const adminProfileCorrect: AdminProfile = {
  ...baseUserData,
  ...validAdminData
};

console.log(adminProfileCorrect.userId);
console.log(adminProfileCorrect.adminLevel);

এক্সেস প্রপার্টি চেকটি স্প্রেড সিনট্যাক্স দ্বারা তৈরি ফলস্বরূপ অবজেক্ট লিটারেলের উপর প্রযোজ্য হয়। যদি এই ফলস্বরূপ লিটারেলে টার্গেট টাইপে ঘোষণা করা হয়নি এমন প্রপার্টি থাকে, তবে টাইপস্ক্রিপ্ট একটি এরর রিপোর্ট করবে।

এক্সেস প্রপার্টি মোকাবেলার কৌশল

যদিও এক্সেস প্রপার্টি চেক উপকারী, তবে এমন বৈধ পরিস্থিতিও রয়েছে যেখানে আপনার অতিরিক্ত প্রপার্টি থাকতে পারে যা আপনি অন্তর্ভুক্ত করতে বা ভিন্নভাবে প্রক্রিয়া করতে চান। এখানে কিছু সাধারণ কৌশল রয়েছে:

১. টাইপ অ্যালিয়াস বা ইন্টারফেসে রেস্ট প্রপার্টি ব্যবহার

আপনি টাইপ অ্যালিয়াস বা ইন্টারফেসের মধ্যে রেস্ট প্যারামিটার সিনট্যাক্স (`...rest`) ব্যবহার করে যেকোনো অবশিষ্ট প্রপার্টি যা স্পষ্টভাবে সংজ্ঞায়িত নয়, তা ক্যাপচার করতে পারেন। এটি এই এক্সেস প্রপার্টিগুলোকে স্বীকার এবং সংগ্রহ করার একটি পরিচ্ছন্ন উপায়।


interface UserProfile {
  id: number;
  name: string;
}

interface UserWithMetadata extends UserProfile {
  metadata: {
    [key: string]: any;
  };
}

// অথবা আরও সাধারণভাবে একটি টাইপ অ্যালিয়াস এবং রেস্ট সিনট্যাক্স দিয়ে:
type UserProfileWithMetadata = UserProfile & {
  [key: string]: any;
};

const user1: UserProfileWithMetadata = {
  id: 1,
  name: 'Bob',
  email: 'bob@example.com',
  isAdmin: true
};

// কোনো এরর নেই, কারণ 'email' এবং 'isAdmin' UserProfileWithMetadata-এর ইনডেক্স সিগনেচার দ্বারা ক্যাপচার করা হয়েছে।
console.log(user1.email);
console.log(user1.isAdmin);

// একটি টাইপ ডেফিনিশনে রেস্ট প্যারামিটার ব্যবহার করার আরেকটি উপায়:
interface ConfigWithRest {
  apiUrl: string;
  timeout?: number;
  // অন্যান্য সমস্ত প্রপার্টি 'extraConfig'-এ ক্যাপচার করুন
  [key: string]: any;
}

const appConfig: ConfigWithRest = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
  featureFlags: {
    newUI: true,
    betaFeatures: false
  }
};

console.log(appConfig.featureFlags);

`[key: string]: any;` বা অনুরূপ ইনডেক্স সিগনেচার ব্যবহার করা যেকোনো অতিরিক্ত প্রপার্টি হ্যান্ডেল করার একটি প্রচলিত উপায়।

২. রেস্ট সিনট্যাক্সসহ ডিস্ট্রাকচারিং

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


interface Employee {
  employeeId: string;
  department: string;
}

function processEmployeeData(data: Employee & { [key: string]: any }) {
  const { employeeId, department, ...otherDetails } = data;

  console.log(`Employee ID: ${employeeId}`);
  console.log(`Department: ${department}`);
  console.log('Other details:', otherDetails);
  // otherDetails-এ এমন যেকোনো প্রপার্টি থাকবে যা স্পষ্টভাবে ডিস্ট্রাকচার করা হয়নি,
  // যেমন 'salary', 'startDate' ইত্যাদি।
}

const employeeInfo = {
  employeeId: 'emp-789',
  department: 'Engineering',
  salary: 90000,
  startDate: '2022-01-15'
};

processEmployeeData(employeeInfo);

// যদিও employeeInfo-এর প্রথমে একটি অতিরিক্ত প্রপার্টি ছিল, এক্সেস প্রপার্টি চেক
// এড়িয়ে যাওয়া হয় যদি ফাংশন সিগনেচার এটি গ্রহণ করে (যেমন, একটি ইনডেক্স সিগনেচার ব্যবহার করে)।
// যদি processEmployeeData-কে কঠোরভাবে 'Employee' হিসেবে টাইপ করা হতো, এবং employeeInfo-তে 'salary' থাকত,
// তবে একটি এরর ঘটত যদি employeeInfo সরাসরি পাস করা একটি অবজেক্ট লিটারেল হতো।
// কিন্তু এখানে, employeeInfo একটি ভেরিয়েবল, এবং ফাংশনের টাইপ অতিরিক্ত প্রপার্টি হ্যান্ডেল করে।

৩. সমস্ত প্রপার্টি স্পষ্টভাবে সংজ্ঞায়িত করা (যদি জানা থাকে)

যদি আপনি সম্ভাব্য অতিরিক্ত প্রপার্টিগুলো জানেন, তবে সবচেয়ে ভালো পদ্ধতি হলো সেগুলোকে আপনার ইন্টারফেস বা টাইপ অ্যালিয়াসে যোগ করা। এটি সবচেয়ে বেশি টাইপ সুরক্ষা প্রদান করে।


interface UserProfile {
  id: number;
  name: string;
  email?: string; // ঐচ্ছিক ইমেল
}

const userWithEmail: UserProfile = {
  id: 2,
  name: 'Charlie',
  email: 'charlie@example.com'
};

const userWithoutEmail: UserProfile = {
  id: 3,
  name: 'David'
};

// যদি আমরা UserProfile-এ নেই এমন একটি প্রপার্টি যোগ করার চেষ্টা করি:
// const userWithExtra: UserProfile = {
//   id: 4,
//   name: 'Eve',
//   phoneNumber: '555-1234'
// }; // এরর: অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'phoneNumber' প্রপার্টিটি 'UserProfile' টাইপে বিদ্যমান নেই।

৪. টাইপ অ্যাসারশনের জন্য `as` ব্যবহার করা (সতর্কতার সাথে)

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


interface ProductConfig {
  id: string;
  version: string;
}

// কল্পনা করুন এটি একটি বাহ্যিক উৎস বা একটি কম কঠোর মডিউল থেকে এসেছে
const externalConfig = {
  id: 'prod-abc',
  version: '1.2',
  debugMode: true // এক্সেস প্রপার্টি
};

// যদি আপনি জানেন যে 'externalConfig'-এ সবসময় 'id' এবং 'version' থাকবে এবং আপনি এটিকে ProductConfig হিসেবে ব্যবহার করতে চান:
const productConfig = externalConfig as ProductConfig;

// এই অ্যাসারশনটি `externalConfig`-এর উপর এক্সেস প্রপার্টি চেক বাইপাস করে।
// তবে, যদি আপনি সরাসরি একটি অবজেক্ট লিটারেল পাস করতেন:

// const productConfigLiteral: ProductConfig = {
//   id: 'prod-xyz',
//   version: '2.0',
//   debugMode: false
// }; // এরর: অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'debugMode' প্রপার্টিটি 'ProductConfig' টাইপে বিদ্যমান নেই।

৫. টাইপ গার্ড

আরও জটিল পরিস্থিতির জন্য, টাইপ গার্ড টাইপগুলোকে সংকীর্ণ করতে এবং শর্তসাপেক্ষে প্রপার্টি হ্যান্ডেল করতে সাহায্য করতে পারে।


interface Shape {
  kind: 'circle' | 'square';
}

interface Circle extends Shape {
  kind: 'circle';
  radius: number;
}

interface Square extends Shape {
  kind: 'square';
  sideLength: number;
}

function calculateArea(shape: Shape) {
  if (shape.kind === 'circle') {
    // টাইপস্ক্রিপ্ট জানে 'shape' এখানে একটি Circle
    console.log(Math.PI * shape.radius ** 2);
  } else if (shape.kind === 'square') {
    // টাইপস্ক্রিপ্ট জানে 'shape' এখানে একটি Square
    console.log(shape.sideLength ** 2);
  }
}

const circleData = {
  kind: 'circle' as const, // লিটারেল টাইপ অনুমানের জন্য 'as const' ব্যবহার করে
  radius: 10,
  color: 'red' // এক্সেস প্রপার্টি
};

// যখন calculateArea-তে পাস করা হয়, ফাংশন সিগনেচার 'Shape' আশা করে।
// ফাংশনটি নিজে সঠিকভাবে 'kind' অ্যাক্সেস করবে।
// যদি calculateArea সরাসরি 'Circle' আশা করত এবং circleData
// একটি অবজেক্ট লিটারেল হিসেবে পেত, 'color' একটি সমস্যা হতো।

// আসুন একটি নির্দিষ্ট সাবটাইপ আশা করা ফাংশন দিয়ে এক্সেস প্রপার্টি চেকটি চিত্রিত করি:

function processCircle(circle: Circle) {
  console.log(`Processing circle with radius: ${circle.radius}`);
}

// processCircle(circleData); // এরর: '{ kind: "circle"; radius: number; color: string; }' টাইপের আর্গুমেন্ট 'Circle' টাইপের প্যারামিটারে অ্যাসাইন করা যাবে না।
                         // অবজেক্ট লিটারেল শুধুমাত্র পরিচিত প্রপার্টি নির্দিষ্ট করতে পারে, এবং 'color' প্রপার্টিটি 'Circle' টাইপে বিদ্যমান নেই।

// এটি ঠিক করতে, আপনি ডিস্ট্রাকচার করতে পারেন বা circleData-এর জন্য আরও অনুমতিমূলক টাইপ ব্যবহার করতে পারেন:

const { color, ...circleDataWithoutColor } = circleData;
processCircle(circleDataWithoutColor);

// অথবা circleData-কে একটি বিস্তৃত টাইপ অন্তর্ভুক্ত করার জন্য সংজ্ঞায়িত করুন:

const circleDataWithExtras: Circle & { [key: string]: any } = {
  kind: 'circle',
  radius: 15,
  color: 'blue'
};
processCircle(circleDataWithExtras); // এখন এটি কাজ করে।

সাধারণ ভুল এবং সেগুলো এড়ানোর উপায়

এমনকি অভিজ্ঞ ডেভেলপাররাও কখনও কখনও এক্সেস প্রপার্টি চেকের কারণে অপ্রস্তুত হতে পারেন। এখানে কিছু সাধারণ ভুল রয়েছে:

বৈশ্বিক প্রেক্ষাপট এবং সেরা অনুশীলন

একটি বৈশ্বিক, বৈচিত্র্যময় উন্নয়ন পরিবেশে কাজ করার সময়, টাইপ সুরক্ষার চারপাশে সামঞ্জস্যপূর্ণ অনুশীলন মেনে চলা অত্যন্ত গুরুত্বপূর্ণ:

উপসংহার

টাইপস্ক্রিপ্টের এক্সেস প্রপার্টি চেকগুলো শক্তিশালী অবজেক্ট টাইপ সুরক্ষা প্রদানের ক্ষমতার একটি ভিত্তিপ্রস্তর। এই চেকগুলো কখন এবং কেন ঘটে তা বোঝার মাধ্যমে, ডেভেলপাররা আরও নির্ভরযোগ্য, কম ত্রুটিপূর্ণ কোড লিখতে পারেন।

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

মূল শিক্ষণীয় বিষয়:

এই নীতিগুলো সচেতনভাবে প্রয়োগ করার মাধ্যমে, আপনি আপনার টাইপস্ক্রিপ্ট কোডের সুরক্ষা এবং রক্ষণাবেক্ষণযোগ্যতা উল্লেখযোগ্যভাবে বাড়াতে পারেন, যা আরও সফল সফটওয়্যার ডেভেলপমেন্টের ফলাফলের দিকে নিয়ে যাবে।

টাইপস্ক্রিপ্ট এক্সেস প্রপার্টি চেকস: আপনার অবজেক্ট টাইপ সুরক্ষাকে শক্তিশালী করুন | MLOG