predefined values for interfaces paired with universal functions

In the development of my project, I am creating a type system centered around commands and their corresponding results. My main objective is to build commands and eventually serialize them into JSON for transmission over the network. Since there will be numerous commands each requiring different fields, I am trying to avoid creating multiple sendCommandXXX() functions. Instead, I aim to have a single generic function that can handle any command seamlessly. Here is what I have implemented so far:

// defining the basic structure required for all commands
interface CommandBase {
  name: string;
}

// sample 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'
}

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

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

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

Currently, it seems repetitive to call sendCommand with both a specific command type in the template field and specifying the name, which would typically remain the same. How can I streamline this process?

Answer №1

What if we approached it from a different angle and tackled it in a different way? Instead of dealing with numerous interfaces and inheritance, we could simplify things by creating a single class that contains the logic for each command. Each command would then refer back to a base command that covers the general setup.

Here's an alternative approach that aims to be more concise and streamlined:

/**
 * Available Commands
 */
enum Commands {
    AddFile = 'AddFile'
}

/**
 * Command for Adding a File
 */
interface CommandAddFile {
    filename: string;
}

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

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

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

In this scenario, you can eliminate the name property altogether and either pass it directly to MyCli.executeCommand as a parameter or set the property before passing it along.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are some methods for extracting the values of keys from an object?

I am facing an issue where I have data collected from a service in the form of an interface type object, but I am unable to find or filter a key within this object. The specific error message I am encountering is: ERROR TypeError: Cannot read property &ap ...

Tips for handling race conditions in useEffects when a component may potentially unmount at any given moment in React

Currently using TypeScript 4 and React 17. Imagine having the following component: This component is part of a React Navigation conditional stack navigator. When the user logs out, the component gets automatically unmounted along with the UI, displaying ...

The overload functionality in Typescript interfaces is not functioning as intended

Here is a snippet of code I'm working with: class A { } class B { } class C { } interface Builder { build(paramOne: A): string; build(paramOne: B, paramTwo: C): number; } class Test implements Builder { build(a: A) { return &apo ...

Error message when running 'npm serve'

Encountering an issue with running the command: npm run serve To address it, I find that logging out or rebooting my Ubuntu 16.04 is necessary. I've verified that no tasks related to node are currently running. Even after uninstalling and reinstall ...

Creating a Map from an array of key-value pairs: A step-by-step guide

Arrays are essential in programming const myArray = [['key1', 'value1'], ['key2', 'value2']]; Creating a Map from an array is a common task. However, sometimes things don't go as planned: const myMap = new M ...

Is it possible to execute TypeScript class methods in asynchronous mode without causing the main thread to be blocked?

Creating an app that retrieves attachments from specific messages in my Outlook mail and stores the data in MongoDB. The challenge lies in the time-consuming process of receiving these attachments. To address this, I aim to execute the task in a separate t ...

Ensuring TypeScript's strict null check on a field within an object that is part of an

When using TypeScript and checking for null on a nullable field inside an object array (where strictNullCheck is set to true), the compiler may still raise an error saying that 'Object is possibly undefined'. Here's an example: interface IA ...

The type 'string' cannot be utilized to index type

Apologies for adding yet another question of this nature, but despite finding similar ones, I am unable to apply their solutions to my specific case. Could someone please assist me in resolving this TypeScript error? The element implicitly has an 'an ...

Exploring the capabilities of the Angular 2 expression parser alongside the functionality of the

Is there a way to create an equivalent of the Angular 1.x ngInit directive in Angular 2? I am familiar with the ngOnInit hook, which is recommended for initialization code. The ngInit directive seems like a quick and declarative way to prototype or fix a ...

NativeScript Angular encountered an error: Uncaught (in promise): There was an issue matching any routes for the URL Segment 'addpatient'

Looking to have my fab button in home.component.ts route to addpatient.component using tabs scaffolding. I've organized my addpatient folder within the home folder, here's a snapshot of my directory structure: app directory rest of app directo ...

What are the constants that TypeScript compiles at runtime?

I'm in the process of developing a TypeScript library that needs to support both Node and Browser environments. Currently, I have been compiling my code twice using tsc with different targets for each environment, and it seems to be functioning correc ...

Props used in styled components are effective, although they may trigger a warning message stating, "Warning: Received `true` for a non-boolean attribute `cen`."

Caution: A non-boolean attribute "cen" received a value of "true". If you intend to render it in the DOM, provide a string instead: cen="true" or cen={value.toString()}. While using Props in Styled-Component with TypeScript and Material-UI, everything func ...

Pass data that has been asynchronously resolved from the parent component to the child component using props in Vue

Main component: <template> <div> <Nav :data="data" /> </div> </template> <script lang="ts"> // ... imports removed for clarity @Component({ components: { Nav: () => import('@/components/Nav.vue&ap ...

Issue with React TSX component in NextJs 14.0.4: Local MP3 files cannot be played, only external online MP3 files work

I have created a component that wraps around HTML audio and source tags. It functions perfectly when playing mp3 files from an external source, like this sound clip . However, it returns a GET 404 error when trying to access local mp3 files. Can anyone exp ...

Angular: Enhancing user experience with draggable and droppable items in a flexible list

My issue involves drag and drop divs within a list. However, the divs seem to move in an unpredictable manner. They do not go where I intend them to be placed. Here is the TypeScript code: timePeriods = [ '1', '2', '3', ...

"Exploring the world of Typescript with the Drawflow library

Currently, I am integrating the fantastic Drawflow library created by @Jerosoler (available at: https://github.com/jerosoler/Drawflow) into my PrimeNg project. User @BobBDE has provided typescript definitions for this library here: https://www.npmjs.com/p ...

The integration of react-color Saturation with @types/react-color is currently unavailable

In my quest to develop a customized color picker, I am utilizing the react-color library (^2.19.3) together with @types/react-color (^3.0.4). The issue arises when trying to import the Saturation component since it is not exported from the types in the ind ...

What are some ways to troubleshoot the TypeScript React demonstration application in Chrome?

Debugging a TypeScript app in the Chrome debugger is a straightforward process. First, you need to configure the tsconfig.json file: "sourceMap": true, Next, install ts-node and set a breakpoint in your TypeScript code using "debugger;" ...

Inversify is a proven method for effectively injecting dependencies into a multitude of domain classes

Struggling to navigate dependencies and injections in a TypeScript-built rest web service without relying heavily on inversify for my domain classes, in line with the dependency inversion principle. Here's an overview of the project structure: core/ ...

Steer clear of duplicating template literal type entries when dealing with optional routes

My code includes a type called ExtractParams that extracts parameters from a URL string: type ExtractParams<Path extends string> = Path extends `${infer Start}(${infer Rest})` ? ExtractParams<Start> & Partial<ExtractParams<Rest>& ...