首页 > 解决方案 > 与泛型函数一起使用的接口的默认值

问题描述

我正在围绕命令和命令结果构建类型系统。最终目标是构建命令并最终通过网络将它们序列化为 JSON。会有很多具有不同必填字段的命令。我希望避免创建许多sendCommandXXX()函数,而是使用可以处理任何命令的通用函数。到目前为止,我所拥有的是:

// base command structure required for all commands
interface CommandBase {
  name: string;
}

// example commands
interface CommandAddFile extends CommandBase {
  name: 'AddFile';
  filename: string;
  contents: string;
}

interface CommandDeleteFile extends CommandBase {
  name: 'DeleteFile';
  filename: string;
}

interface CommandRefreshResults extends CommandBase {
  name: 'RefreshResults'
}

// result structure
interface CommandResult {
  success: boolean;
  error?: string;
}

async sendCommand<T>(opts: T): Promise<CommandResult> {
  // ... send `opts` over network
}

sendCommand<CommandAddFile>({
  name: 'AddFile',
  filename: 'test.txt',
  contents: 'test'
}).then(res => {
  console.log(res.success);
});

现在,使用模板字段中的特定命令类型和指定来调用 sendCommand 感觉是重复的name,它总是希望与一对相同。我怎样才能简化这个?

标签: typescriptooptypescript-generics

解决方案


如何改变它并以另一种方式攻击它?您可以创建一个包含每个命令的逻辑的类,而不是拥有许多不同的接口和继承。然后所有命令调用具有通用设置的基本命令。

以下是我认为可能更简洁和统一的内容:

/**
 * Command Names
 */
enum Commands {
    AddFile = 'AddFile'
}

/**
 * Add File
 */
interface CommandAddFile {
    filename: string;
}

/**
 * Cli class with static methods
 */
class MyCli {
    /**
     * Base command execution
     * @param opts
     */
    private static executeCommand<T>(commandName: string, opts: T): T {
        // ...
        return {} as T;
    }

    /**
     * Adds a file
     * @param opts
     * @constructor
     */
    static AddFile(opts: CommandAddFile): Promise<CommandAddFile> {
        const result = this.executeCommand<CommandAddFile>(Commands.AddFile, opts);
        return Promise.resolve(result);
    }
}

// Usage
MyCli.AddFile({} as CommandAddFile).then( res => console.log(res) );

然后,您可以将name道具全部放在一起,然后将其作为参数传递给MyCli.executeCommand或在传递之前设置属性。


推荐阅读