تایپ empty object در تایپ اسکریپت

تایپ empty object، یعنی

{}
{}در تایپ اسکریپت به شکلی که ما انتظار داریم رفتار نمی‌کند. یعنی به جای نمایش یک آبجکت خالی، هر مقداری را نشان می‌دهد به جز مقادیر
null
nullو
undefined
undefined.

دلیل این اتفاق این است که سیستم تایپ در تایپ اسکریپت به شکل structural است، نه nominal. بنابراین همه چیز به جز

null
nullو
undefined
undefinedیک آبجکت هستند. در نتیجه هر چیزی را می‌توانیم به یک آبجکت خالی نسبت دهیم.

اگر می‌خواهیم یک شی خالی را نشان دهیم، می‌توانیم به جای آن از

Record<string, never>
Record<string, never>استفاده کنیم.

تایپ empty object

تایپ empty object در تایپ اسکریپت واقعاً آنطور که انتظار داریم رفتار نمی‌کند. یعنی این که نشان دهنده any object نیست. در عوض، هر مقداری که

null
nullیا
undefined
undefinedنباشد را ارائه می‌دهد:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const example1: {} = "str";
const example2: {} = 123;
const example3: {} = true;
const example4: {} = {
foo: "whatever",
};
const example1: {} = "str"; const example2: {} = 123; const example3: {} = true; const example4: {} = { foo: "whatever", };
const example1: {} = "str";
const example2: {} = 123;
const example3: {} = true;
const example4: {} = {
  foo: "whatever",
};

در این مثال، ما

example1
example1را به عنوان یک آبجکت خالی ایجاد می‌کنیم، اما می‌توانیم یک رشته را به آن ارسال کنیم. همچنین می‌توانیم یک عدد به آن بفرستیم. علاوه بر این می توانیم یک Boolean و یا هر آبجکت دیگری را به آن ارسال نماییم.

تنها چیزهایی که نمی‌توانیم به آن ارسال کنیم مقادیر

null
nullیا
undefined
undefinedاست:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const example5: {} = null;
Type 'null' is not assignable to type '{}'.
const example6: {} = undefined;
Type 'undefined' is not assignable to type '{}'.
const example5: {} = null; Type 'null' is not assignable to type '{}'. const example6: {} = undefined; Type 'undefined' is not assignable to type '{}'.
const example5: {} = null;
Type 'null' is not assignable to type '{}'.
const example6: {} = undefined;
Type 'undefined' is not assignable to type '{}'.

اگر از ESLint استفاده می‌کنیم، حتی ممکن است با خطا زیر مواجه شویم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Don't use {} as a type. {} actually means "any non-nullish value".
Don't use {} as a type. {} actually means "any non-nullish value".
Don't use {} as a type. {} actually means "any non-nullish value".

در این مقاله به شکل دقیق بررسی می‌کنیم که چرا این توصیه خوب است.

تایپ object

این موضوع همچنین با تایپ

Object
Objectنیز اتفاق می‌افتد، که به نظر می‌رسد فقط یک نام مستعار برای
{}
{}می‌باشد:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const obj1: Object = "str";
const obj2: Object = null;
Type 'null' is not assignable to type 'Object'.
const obj1: Object = "str"; const obj2: Object = null; Type 'null' is not assignable to type 'Object'.
const obj1: Object = "str";
const obj2: Object = null;
Type 'null' is not assignable to type 'Object'.

بنابراین این دقیقاً به همان شیوه رفتار می‌کند. در نتیجه ما نیز نباید از این تایپ

Object
Objectاستفاده کنیم.

نمایش یک آبجکت خالی

اگر بخواهیم نوعی آبجکت خالی را نشان دهیم، می‌توانیم از

Record<PropertyKey, never>
Record<PropertyKey, never>استفاده کنیم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
type EmptyObj = Record<PropertyKey, never>;
const emptyObj1: EmptyObj = {};
const emptyObj2: EmptyObj = {
foo: "whatever",
Type 'string' is not assignable to type 'never'.
};
const emptyObj3: EmptyObj = "str";
Type 'string' is not assignable to type 'EmptyObj'.
const emptyObj4: EmptyObj = 123;
Type 'number' is not assignable to type 'EmptyObj'.
type EmptyObj = Record<PropertyKey, never>; const emptyObj1: EmptyObj = {}; const emptyObj2: EmptyObj = { foo: "whatever", Type 'string' is not assignable to type 'never'. }; const emptyObj3: EmptyObj = "str"; Type 'string' is not assignable to type 'EmptyObj'. const emptyObj4: EmptyObj = 123; Type 'number' is not assignable to type 'EmptyObj'.
type EmptyObj = Record<PropertyKey, never>;
 
const emptyObj1: EmptyObj = {};
const emptyObj2: EmptyObj = {
  foo: "whatever",
Type 'string' is not assignable to type 'never'.
};
const emptyObj3: EmptyObj = "str";
Type 'string' is not assignable to type 'EmptyObj'.
const emptyObj4: EmptyObj = 123;
Type 'number' is not assignable to type 'EmptyObj'.

کاری که این کد کار انجام می‌دهد این است که می‌توانیم یک آبجکت خالی را ارسال کنیم. این کار، ما را از ارسال هر چیزی که property روی آن است باز می‌دارد. همچنین از ارسال موارد primitive یا null و یا undefined نیز جلوگیری می‌کند.

توابع Constrain

این مفهوم تنها زمانی ممکن است مفید باشد که بخواهیم یک محدودیت واقعاً گسترده برای یک تابع داشته باشیم. فرض کنید می‌خواهیم مطمئن شویم چیزی که به تابع ارسال می‌کنیم،

null
nullیا
undefined
undefinedنیست:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const myFunc = (constraint: {}) => {};
myFunc("str");
myFunc(123);
myFunc(true);
const myFunc = (constraint: {}) => {}; myFunc("str"); myFunc(123); myFunc(true);
const myFunc = (constraint: {}) => {};
 
myFunc("str");
myFunc(123);
myFunc(true);

اما حتی در این شرایط، نمی‌توانیم به هیچ ویژگی در

constraint
constraintدسترسی داشته باشیم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const myFunc = (constraint: {}) => {
constraint.foo;
Property 'foo' does not exist on type '{}'.
};
const myFunc = (constraint: {}) => { constraint.foo; Property 'foo' does not exist on type '{}'. };
const myFunc = (constraint: {}) => {
  constraint.foo;
Property 'foo' does not exist on type '{}'.
};

با این خطا مواجه می‌شویم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Property 'foo' does not exist on type ''.
Property 'foo' does not exist on type ''.
Property 'foo' does not exist on type ''.

این اتفاق می‌افتد زیرا ما در حال تلاش برای دسترسی به یک ویژگی در یک آبجکت خالی هستیم. بنابراین کار زیاد مفیدی نیست.

توابع Generic

تنها جایی که این کار می‌تواند مفید باشد، یا حداقل جایی که می‌خواهیم در بخش به آن بپردازیم، به عنوان یک محدودیت در یک تابع generic است.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const myGenericFunc = <T extends {}>(t: T) => {
return t;
};
const result1 = myGenericFunc("str");
const result2 = myGenericFunc(123);
const result3 = myGenericFunc(true);
const myGenericFunc = <T extends {}>(t: T) => { return t; }; const result1 = myGenericFunc("str"); const result2 = myGenericFunc(123); const result3 = myGenericFunc(true);
const myGenericFunc = <T extends {}>(t: T) => {
  return t;
};
 
const result1 = myGenericFunc("str");
const result2 = myGenericFunc(123);
const result3 = myGenericFunc(true);

داخل تایع

myGenericFunc
myGenericFunc، می‌خواهیم مطمئن شویم که نمی‌توانیم
null
nullیا
undefined
undefinedرا به تابع generic ارسال کنیم. اگر ماوس را روی
myGenericFunc
myGenericFuncنگه داریم، می‌بینیم که
str
strرا می‌گیرد و آن را در نتایج return می‌کند.

اما زمانی که سعی می‌کنیم به صورت null یا undefined ارسال کنیم، با خطا مواجه می‌شویم.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const result4 = myGenericFunc(null);
Argument of type 'null' is not assignable to parameter of type '{}'.
const result5 = myGenericFunc(undefined);
Argument of type 'undefined' is not assignable to parameter of type '{}'.
const result4 = myGenericFunc(null); Argument of type 'null' is not assignable to parameter of type '{}'. const result5 = myGenericFunc(undefined); Argument of type 'undefined' is not assignable to parameter of type '{}'.
const result4 = myGenericFunc(null);
Argument of type 'null' is not assignable to parameter of type '{}'.
const result5 = myGenericFunc(undefined);
Argument of type 'undefined' is not assignable to parameter of type '{}'.

جمع‌بندی

با توجه به مفاهیمی که در این مقاله با آن‌ها آشنا شدیم، ما نباید در هیچ بخشی از تایپ

{}
{}استفاده کنیم. زیرا یک قانون linting پیدا کردیم که ما را از استفاده از آن باز می‌دارد. به همین دلیل است که این تایپ، چیزی که ما فکر می‌کنیم را نشان نمی‌دهد، اما گاهی اوقات برای محدود کردن genericها مفید می‌باشد.

دیدگاه‌ها:

افزودن دیدگاه جدید