我目前有一个软件,其功能会根据安装的操作系统而变化(例如
Windows
或Linux
)。
所以我只想创建一个适合操作系统的对象,具体取决于静态配置变量config.soft.type
(仅等于"windows"
或"linux"
的字符串)。
在程序启动时,我的类需要同步,因此我将构造函数设为私有,并为两个类添加了
async static synchronize()
方法,该方法将为 Windows 或 Linux 创建并返回 OperatingSystem
对象。
如何使用正确的类型正确实例化
Windows
和 Linux
类的存储库?
// index.ts
...
const { type }: 'windows' | 'linux' = config.soft;
const software = type === 'windows'
? new Windows.synchronize(toto, tata, tutu)
? new Linux.synchronize(toto, tata, tutu);
software.down();
aRandomFunction(software);
...
我想将
software
(类型为 Windows | Linux
)传递给其他函数(例如 aRandomFunction()
)并使用 OperatingSystem
作为 software
的类型(因为 Windows
和 Linux
类都来自OperatingSystem
,但我不知道是否需要明确地将“基本”函数(两个类共享但重载)放在OperatingSystemInterface
)
我的类/接口定义如下:
// OperatingSystem's Interface,
abstract class OperatingSystemInterface
// The implementation of OperatingSystemInterface, I expect Windows and Linux to have `down()` method defined in OperatingSystem without redeclaring it in their interfaces
class OperatingSystem implements OperatingSystemInterface
// OperatingSystem for Windows, with overloaded methods to fitt Windows's need and some more method / properties specific to Windows's class
class Windows extends OperatingSystem implements WindowsInterface
// OperatingSystem for Linux
class Linux extends OperatingSystem implements LinuxInterface
目前,我遇到错误,例如:
error TS2420: Class 'Windows' incorrectly implements interface 'WindowsInterface'.
Property 'synchronize' is missing in type 'Windows' but required in type 'WindowsInterface'.
8 export class Windows extends OperatingSystem implements WindowsInterface {
~~~~~
src/services/OperatingSystems/types.ts:70:3
70 synchronize(
~~~~~~~~~~~~
71 client: Client,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
74 toto: string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
75 ): Promise<WindowsInterface>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'synchronize' is declared here.
但我确实声明了,是因为原型不匹配吗? (在接口中,我声明了 *Interface 的
synchronize()
的返回类型,并且在类中,我返回了已实现类本身的对象(例如,Linux 而不是 LinuxInterface),但是我应该在 Linux
中导入
types.ts
吗?将其作为返回类型放入
LinuxInterface
的 synchronize()
中?感觉不太对。
完整代码:
// types.ts (where I stored my interfaces)
import { Client } from 'client';
import { Config } from 'config';
export abstract class OperatingSystemInterface {
abstract readonly client: Client;
abstract readonly config: Config;
abstract down(): void;
}
export interface WindowsInterface extends OperatingSystemInterface {
start(): Promise<void>;
someWindowsRelatedMethod(): Promise<number>;
anotherWindowsMethod(path: string, value: number): Promise<void>;
synchronize(
protected client: Client,
protected config: Config,
toto: string
): Promise<WindowsInterface>;
}
export interface LinuxInterface extends OperatingSystemInterface {
start(): Promise<void>;
synchronize(
protected client: Client,
protected config: Config,
toto: string
): Promise<LinuxInterface>;
}
// OperatingSystem.ts
// Base class which `Windows` and `Linux` overload methods
export class OperatingSystem implements OperatingSystemInterface {
public readonly informations: Information[] = [];
constructor(
protected client: Client,
protected config: Config,
toto: string,
) {
this._toto = toto;
this.client.subscribe(`${config.message}/toto/tata`);
this.client.subscribe(`${config.message}/titi`);
}
get toto(): string {
return this._toto;
}
down(): void {
this.client.stop();
}
}
// Linux.ts
import { Client } from 'client';
import { Config } from 'config';
export class Linux extends OperatingSystem implements LinuxInterface {
private constructor(
protected client: Client,
protected config: Config,
toto: string
) {
super(client, config, toto);
}
static async synchronize(
client: Client,
config: Config,
toto: string
): Promise<Linux> {
const operatingSystem = new Linux(client, config, toto);
// here some specific code to Linux
...
return operatingSystem;
}
async start(): Promise<void> {
this.client.on('message', (message: Message) => {
// some Linux's specific code
});
}
}
// Windows.ts
import { Client } from 'client';
import { Config } from 'config';
export class Windows extends OperatingSystem implements WindowsInterface {
// it represent the Application's permission over the Windows's API
private windowsInfo: Config = {
role: 'Viewer',
isSuperAdmin: true,
};
private constructor(
protected client: Client,
protected config: Config,
toto: string
) {
super(client, config, toto);
}
static async synchronize(
client: Client,
config: Config,
toto: string
): Promise<Windows> {
const operatingSystem = new Windows(client, config, toto);
// here some Windows' specific code
...
return operatingSystem;
}
async start(): Promise<void> {
this.client.on('message', (message: Message) => {
// some Window's specific code
this.someWindowsRelatedMethod();
});
}
someWindowsRelatedMethod(): Promise<number> {
...
}
anotherWindowsMethod(path: string, value: number): Promise<void> {
...
}
}
我可以看到一些问题:
class
,而不是 interface
错误信息正确:
error TS2420: Class 'Windows' incorrectly implements interface 'WindowsInterface'.
Property 'synchronize' is missing in type 'Windows' but required in type 'WindowsInterface'.
您的
WindowsInterface
接口声明了 synchronize()
方法,但您已在类上将其作为静态方法实现。
因此,从编译器的角度来看,您的类缺少
synchronize()
方法,并且它给您带来了该错误。
不可能在接口上定义静态成员;静态成员属于类,而不是接口。
考虑到您在其他地方如何使用该功能,您应该从界面中删除
synchronize()
。
synchronize()
功能的使用不正确您的静态
synchronize()
函数已经实例化您的类(即 new
)并返回新实例。
基本上,这就像您试图做new new Windows(...)
,这是不正确的。
并且您的
synchronize()
函数正在返回一个 Promise - 您将需要链接该 Promise 或使用 await
来“解开”该 Promise 以访问其中的值。
static async synchronize(
client: Client,
config: Config,
toto: string
): Promise<Windows> {
^^^^^^^^^^^^^^^^ - you're returning a promise here
const operatingSystem = new Windows(client, config, toto);
^^^^^^^^^^^ - you're constructing the instances here
// here some Windows' specific code
...
return operatingSystem;
}
// index.ts
...
const { type }: 'windows' | 'linux' = config.soft;
const software = type === 'windows'
? new Windows.synchronize(toto, tata, tutu)
^^^^^^^^^^^ - this is a `Promise<Windows>`
// don't use `new` here
// you'll need to "unwrap" the promise to access the Windows instance
? new Linux.synchronize(toto, tata, tutu);
^^^^^^^^^ - same error here
// You need to chain the promise or use `await` to access the value inside the `software` promise
software.down();
aRandomFunction(software);
如果您可以使用顶级
await
,那么这是最简单的代码版本:
// index.ts
...
const { type }: 'windows' | 'linux' = config.soft;
const software = type === 'windows'
? await Windows.synchronize(toto, tata, tutu)
? await Linux.synchronize(toto, tata, tutu);
software.down();
aRandomFunction(software);