در تایپاسکریپت، چگونه میتوان نوع یک کلاس خصوصی را بدون صادر کردن خود کلاس صادر کرد
من یک ماژول دارم که در آن متد عمومی یک کلاس عمومی، یک نمونه جدید از یک کلاس خصوصی ایجاد کرده و برمیگرداند. الزام این است که MyClassPrivateHelper تنها توسط MyClass نمونهسازی شود.
class MyClassPrivateHelper {
constructor(private cls: MyClass) {
}
public someHelperMethod(arg): void {
this.cls.someMethod();
}
}
export class MyClass {
public createHelper(): MyClassPrivateHelper { // error here
return new MyClassPrivateHelper(this);
}
public someMethod(): void {
/**/
}
}
با این تنظیم، تایپاسکریپت خطا گزارش میدهد:
[ts] Return type of public method from exported class has or is using private name 'MyClassPrivateHelper'.هدف من این است که فقط «نوع» کلاس خصوصی را صادر کنم بدون اینکه کدی که از ماژول استفاده میکند بتواند مستقیماً آن را نمونهسازی کند. به عنوان مثال
const mycls = new module.MyClass();
// should be allowed
const helper: MyClassPrivateHelper = mycls.createHelper();
// should not be allowed
const helper = new module.MyClassPrivateHelper();
من تلاش کردهام از typeof به این صورت استفاده کنم ولی موفق نبودهام.
export type Helper = typeof MyClassPrivateHelper
شاید من درک نمیکنم که «typeof» چگونه کار میکند. سوالهای من اینها هستند:
- چرا صادرات نوع با استفاده از
typeofکار نمیکند؟ - چطور میتوانم نوع را صادر کنم بدون اینکه کلاس خصوصی خارج از ماژول را افشا کنم؟
پاسخ شماره ۱
چرا صادر کردن نوع با استفاده از typeof کار نمیکند؟
export type MyInterface = typeof MyClassPrivateHelper
در این مثال MyInterface نوع تابع سازنده است، اما شما میخواهید نوع نمونههایی که این سازنده میتواند تولید کند را صادر کنید.
چطور میتوانم نوع را صادر کنم بدون اینکه کلاس خصوصی خارج از ماژول را افشا کنم؟
مثل این:
export type MyInterface = InstanceType<typeof MyClassPrivateHelper>
InstanceType به طور مختصر در اینجا توضیح داده شده است: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html.
بهطور متناوب، من متوجه شدم که مورد زیر نیز کار میکند:
type Interface<T> = { [P in keyof T]: T[P] }
export interface MyInterface extends Interface<MyClassPrivateHelper> {}
نوع Interface اساساً تمام ویژگیهای عمومی از T را کپی میکند، که سپس از آن برای اعلام یک رابط جدید استفاده میکنیم.
برای جزئیات بیشتر به https://github.com/Microsoft/TypeScript/issues/471#issuecomment-381842426 مراجعه کنید.
پاسخ شماره ۲
شما باید یک رابط ایجاد کنید و آن را صادر کنید:
export interface IMyHelper {
someHelperMethod(arg): void;
}
و سپس اجازه دهید کمککننده آن را پیادهسازی کند:
class MyClassPrivateHelper implements IMyHelper {
constructor(private cls: MyClass) {
}
public someHelperMethod(arg): void {
this.cls.someMethod();
}
}
کلاس عمومی رابط را باز میگرداند
export class MyClass {
public createHelper(): IMyHelper {
return new MyClassPrivateHelper(this);
}
public someMethod(): void {
/**/
}
}
از خارج، کمککننده دوباره با رابط خود ارجاع داده میشود:
const helper: IMyHelper = mycls.createHelper();
