۵۰ درصد تخفیف ویژه برای همه دوره‌ها از شنبه

کار با آرایه‌های readonly در تایپ اسکریپت ممکن است گاهی اوقات کمی دردسرساز باشد. فرض کنید می‌خواهیم یک آرایه از مسیرها، به عنوان const تعریف کنیم. ما با انجام این کار می‌توانیم از مسیرهایی که برای یک تایپ تعریف کرده‌ایم استفاده مجدد نماییم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const arrayOfRoutes = [
{ path: "/home", component: Home },
{ path: "/about", component: About },
] as const;
type Route = (typeof arrayOfRoutes)[number]["path"];
type Route = "/home" | "/about"
const arrayOfRoutes = [ { path: "/home", component: Home }, { path: "/about", component: About }, ] as const; type Route = (typeof arrayOfRoutes)[number]["path"]; type Route = "/home" | "/about"
const arrayOfRoutes = [
  { path: "/home", component: Home },
  { path: "/about", component: About },
] as const;
 
type Route = (typeof arrayOfRoutes)[number]["path"];
      
type Route = "/home" | "/about"

اما اگر بخواهیم مطمئن شویم که

arrayOfRoutes
arrayOfRoutesبا تایپ خاصی مطابقت دارد، چه کاری باید انجام دهیم؟ برای آن می‌توانیم از satisfies استفاده کنیم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const arrayOfRoutes = [
{ path: "/home", component: Home },
{ path: "/about", component: About },
] as const satisfies {
path: string;
component: React.FC;
}[];
// Type is 'readonly' and cannot be
// assigned to a mutable type
const arrayOfRoutes = [ { path: "/home", component: Home }, { path: "/about", component: About }, ] as const satisfies { path: string; component: React.FC; }[]; // Type is 'readonly' and cannot be // assigned to a mutable type
const arrayOfRoutes = [
  { path: "/home", component: Home },
  { path: "/about", component: About },
] as const satisfies {
  path: string;
  component: React.FC;
}[];
// Type is 'readonly' and cannot be
// assigned to a mutable type

تنها مشکلی که وجود دارد این است که در نسخه ۵٫۲ تایپ اسکریپ، این یک خطا می‌دهد، اما چرا؟

مقایسه آرایه‌های readonly و آرایه‌های قابل تغییر

این اتفاق به این دلیل است که

arrayOfRoutes
arrayOfRoutesیک آرایه readonly است و ما نمی‌توانیم یک آرایه قابل تغییر را با یک readonly ایجاد کنیم. بنابراین، راه حل این مشکل این است که تایپ مورد نظرمان را به یک آرایه
readonly
readonlyتبدیل نماییم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const arrayOfRoutes = [
{ path: "/home", component: Home },
{ path: "/about", component: About },
] as const satisfies readonly {
path: string;
component: React.FC;
}[];
// No more error!
const arrayOfRoutes = [ { path: "/home", component: Home }, { path: "/about", component: About }, ] as const satisfies readonly { path: string; component: React.FC; }[]; // No more error!
const arrayOfRoutes = [
  { path: "/home", component: Home },
  { path: "/about", component: About },
] as const satisfies readonly {
  path: string;
  component: React.FC;
}[];
 
// No more error!

اکنون که از یک آرایه readonly استفاده می‌کنیم، هیچ خطایی ایجاد نمی‌شود.

پارامترهای تایپ Const

هنگام استفاده از پارامترهای تایپ const نیز همین امر صادق است، حتی ممکن است کمی حساسیت بیشتری نسبت به حالت قبل داشته باشد.

در این موقعیت،

const
constچیزی را که به
T
Tمنتقل شده است، استنتاج می‌کند که گویی
as const
as constاست. اما اگر بخواهیم آن را با یک آرایه محدود کنیم، کار نمی‌کند.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const returnWhatIPassIn = <const T extends any[]>(t: T) => {
return t;
};
// result is any[] in TS 5.2!
const result = returnWhatIPassIn(["a", "b", "c"]);
const returnWhatIPassIn = <const T extends any[]>(t: T) => { return t; }; // result is any[] in TS 5.2! const result = returnWhatIPassIn(["a", "b", "c"]);
const returnWhatIPassIn = <const T extends any[]>(t: T) => {
  return t;
};
 
// result is any[] in TS 5.2!
const result = returnWhatIPassIn(["a", "b", "c"]);

راه حل این مشکل برای نسخه‌های قبل از ۵٫۳ تایپ اسکریپت، این بود که

readonly
readonlyبه پارامتر type اضافه کنیم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const returnWhatIPassIn = <const T extends readonly any[]>(
t: T
) => {
return t;
};
// result is ['a', 'b', 'c']!
const result = returnWhatIPassIn(["a", "b", "c"]);
const returnWhatIPassIn = <const T extends readonly any[]>( t: T ) => { return t; }; // result is ['a', 'b', 'c']! const result = returnWhatIPassIn(["a", "b", "c"]);
const returnWhatIPassIn = <const T extends readonly any[]>(
  t: T
) => {
  return t;
};
 
// result is ['a', 'b', 'c']!
const result = returnWhatIPassIn(["a", "b", "c"]);

اما برای اینکه بتوانیم این مشکل را پیدا کرده و برطرف نماییم باید دانش عمیق در مورد نحوه عملکرد پارامترهای تایپ const داشته باشیم که البته کار دشواری است.

چگونه نسخه ۵٫۳ تایپ اسکریپت آن را رفع کرده است؟

از نسخه ۵٫۳، تایپ اسکریپت قوانین مربوط به آرایه‌های readonly را کاهش داده است. بنابراین در این دو موقعیت، تایپ اسکریپت مفیدتر عمل می‌کند. اکنون کلمه کلیدی satisfies به ما این امکان را می‌دهد تا مشکل آرایه‌های readonly را برطرف نماییم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// This would error in 5.2, but is allowed in 5.3!
const array = ["a", "b", "c"] as const satisfies string[];
const array: ["a", "b", "c"]
// This would error in 5.2, but is allowed in 5.3! const array = ["a", "b", "c"] as const satisfies string[]; const array: ["a", "b", "c"]
// This would error in 5.2, but is allowed in 5.3!
const array = ["a", "b", "c"] as const satisfies string[];
       
const array: ["a", "b", "c"]

حال پارامترهای تایپ Const به جای پیش‌فرض بودن به محدودیت‌های خود، تایپ ارسال شده را استنباط می‌کنند:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const returnWhatIPassIn = <const T extends any[]>(t: T) => {
return t;
};
// result is any[] in TS 5.2, but ['a', 'b', 'c'] in 5.3
const result = returnWhatIPassIn(["a", "b", "c"]);
const result: ["a", "b", "c"]
const returnWhatIPassIn = <const T extends any[]>(t: T) => { return t; }; // result is any[] in TS 5.2, but ['a', 'b', 'c'] in 5.3 const result = returnWhatIPassIn(["a", "b", "c"]); const result: ["a", "b", "c"]
const returnWhatIPassIn = <const T extends any[]>(t: T) => {
  return t;
};
 
// result is any[] in TS 5.2, but ['a', 'b', 'c'] in 5.3
const result = returnWhatIPassIn(["a", "b", "c"]);
        
const result: ["a", "b", "c"]

باید به این نکته توجه داشته باشیم که یک تفاوت کوچک وجود دارد. اگر بخواهید

readonly string[]
readonly string[]را به جای
string[]
string[]مشخص کنیم، یک آرایه readonly را دریافت خواهیم کرد.

بنابراین اگر قصد داریم یک آرایه readonly بازگردانده شود، باید readonly را مشخص نماییم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// This would error in 5.2, but is allowed in 5.3!
const array = [
const array: readonly ["a", "b", "c"]
"a",
"b",
"c",
] as const satisfies readonly string[];
const returnWhatIPassIn = <const T extends readonly any[]>(
t: T
) => {
return t;
};
// result is any[] in TS 5.2, but ['a', 'b', 'c'] in 5.3
const result = returnWhatIPassIn(["a", "b", "c"]);
const result: readonly ["a", "b", "c"]
// This would error in 5.2, but is allowed in 5.3! const array = [ const array: readonly ["a", "b", "c"] "a", "b", "c", ] as const satisfies readonly string[]; const returnWhatIPassIn = <const T extends readonly any[]>( t: T ) => { return t; }; // result is any[] in TS 5.2, but ['a', 'b', 'c'] in 5.3 const result = returnWhatIPassIn(["a", "b", "c"]); const result: readonly ["a", "b", "c"]
// This would error in 5.2, but is allowed in 5.3!
const array = [
       
const array: readonly ["a", "b", "c"]
  "a",
  "b",
  "c",
] as const satisfies readonly string[];
 
const returnWhatIPassIn = <const T extends readonly any[]>(
  t: T
) => {
  return t;
};
 
// result is any[] in TS 5.2, but ['a', 'b', 'c'] in 5.3
const result = returnWhatIPassIn(["a", "b", "c"]);
        
const result: readonly ["a", "b", "c"]

این موضوع یک پیشرفت بسیار بزرگ است که هم پارامترهای تایپ

const
constو هم کار با آن را بسیار آسان‌تر می‌کند.