استخراج روش های کلاس: نحوه استخراج یک رابط از یک کلاس
در برنامه نویسی شی گرا (OOP) معمولاً یک رابط تعریف می کنیم و آن رابط را در کلاس های مختلف پیاده سازی می کنیم. در TypeScript می توانیم برعکس عمل کنیم. ما میتوانیم یک کلاس را پیادهسازی کنیم و یک رابط از آن کلاس بدون تعریف واقعی آن استخراج کنیم. چرا ما هرگز نیاز به انجام این کار داریم؟ خوب، این می تواند در سناریوهای مختلف، مانند ایجاد مدل های ایمن برای کلاس های جاوا اسکریپت، بسیار مفید باشد. این تضمین می کند که کلاس mock تمام متدهای کلاس اصلی را بدون نیاز به تعریف یک رابط جداگانه پیاده سازی می کند.
استخراج نوع نمونه
اولین قدم استخراج نوع نمونه از کلاس است. به طور پیش فرض، وقتی نوع یک کلاس را در TypeScript بازیابی می کنید، نوع سازنده کلاس را دریافت می کنید، نه نوع نمونه کلاس را. برای کار با نوع نمونه، یک نوع ابزار را تعریف می کنیم:
type ExtractInstanceType<T> = T extends new (...args: any[]) => infer R ? R : T extends { prototype: infer P } ? P : any;
اینجا ExtractInstanceType<T>
ابتدا سعی می کند نوع نمونه را از سازنده کلاس استخراج کند. اگر سازنده برای عموم قابل دسترسی نباشد، نوع نمونه از ویژگی نمونه اولیه کلاس استخراج می شود. این تفاوت اصلی با نوع ابزار داخلی TypeScript است InstanceType<T>
، که فقط با سازنده عمومی کار می کند.
به عنوان مثال، کلاس زیر را با یک سازنده خصوصی در نظر بگیرید:
class SomeClass {
private constructor() {}
someMethod() {}
}
//> OK: Type is SomeClass
type SomeClassInstance = ExtractInstanceType<typeof SomeClass>;
//> Error: Type 'typeof SomeClass' does not satisfy the constraint 'abstract new (...args: any) => any'.
type SomeClassInstanceError = InstanceType<typeof SomeClass>
استخراج متدها از نوع نمونه
وقتی نوع نمونه را داشتیم، میتوانیم متدهای آن را استخراج کنیم. برای انجام این کار، دو نوع ابزار دیگر را تعریف می کنیم:
type ExtractMethodNames<T> = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never }[keyof T];
type ExtractMethods<T> = Pick<T, ExtractMethodNames<T>>;
ExtractMethodNames<T>
یک نوع نگاشت است که روی همه کلیدهای تکرار می شود T
و بررسی می کند که آیا هر کلید با یک متد مطابقت دارد یا خیر. اگر این کار را کرد، کلید حفظ می شود. در غیر این صورت، به آن اختصاص داده شده است never
نوع
ExtractMethods<T>
سپس از Pick
نوع ابزار برای انتخاب فقط آن خصوصیات از T که متد هستند.
حال، بیایید از این انواع ابزار برای استخراج متدها استفاده کنیم SomeClassInstance
:
//> Type contains methods from SomeClass
type SomeClassMethods = ExtractMethods<SomeClassInstance>;
در این مثال، SomeClassMethods
نوعی است که فقط شامل متدهای یک نمونه از SomeClass
.
پیاده سازی کلاس با متدهای استخراج شده
در نهایت، بیایید ببینیم که چگونه یک کلاس جدید تعریف کنیم که این را پیاده سازی می کند SomeClassMethods
نوع با اطمینان از نوع بودن یک کلاس SomeClassMethods
، اطمینان حاصل می کنیم که کلاس همان متدهای نمونه ای از کلاس را دارد SomeClass
.
در اینجا نحوه انجام این کار آمده است:
//> OK: Class implements methods from SomeClass
class SomeClassMock implements SomeClassMethods {
someMethod() {}
}
//> Error: Class 'SomeClassMockError' incorrectly implements interface 'SomeClassMethods'.
//> Property 'someMethod' is missing in type 'SomeClassMockError' but required in type 'SomeClassMethods'
class SomeClassMockError implements SomeClassMethods {
anotherMethod() {}
}
در این کد، SomeClassMock
کلاس جدیدی است که برنامه را پیاده سازی می کند SomeClassMethods
نوع این تضمین می کند که SomeClassMock
شامل الف someMethod
تابع. اگر SomeClassMock
الف را شامل نمی شود someMethod
تابع، یا اگر someMethod
عملکرد در SomeClassMock
با یکی در مطابقت ندارد SomeClassMethods
، TypeScript یک خطای کامپایل ایجاد می کند.
TypeScript Playground مثال
نمونه کامل آن در TypeScript Playground موجود است تا خودتان آن را آزمایش کنید.
امیدوارم این پست برای شما مفید بوده باشد. اگر سوال یا نظری دارید، در زیر آن را مطرح کنید. اگر می خواهید با من ارتباط برقرار کنید، می توانید من را در لینکدین یا گیت هاب پیدا کنید. با تشکر برای خواندن!