angulartypescripttypescomplex-data-types

Interface whose properties are of types A and B only in TypeScript?


I've created a holder for my configs with type ButtonConfigs like this (as suggested in this answer).

export interface ButtonConfigs {
  [key: string]: ButtonConfig;
}

The I continued with other components' configs as well so that every type has its own config property in the component.

...
buttonConfigs: ButtonConfigs = {};
folderConfigs: FolderConfigs = {};
txtBoxConfigs: TxtBoxConfigs = {};
...

Then it hit me that I should be able to aggregate all the configs to a common property. It really makes sense in my case, too.

However, I'm not sure if I can change the interface in such a way that it allows for different types, still restricting the contents of the configs not to be any. My current approach is poorly designed.

export interface Configs {
  [key: string]: any;
}

How can I tell TypeScript that the type of the field should be TextBoxConfig, ButtonConfig or FolderConfig but nothing else?


Solution

  • Have you tried to use a union type?

    interface ButtonConfig {
      a: string;
    }
    interface FolderConfigs {
      b: number;
    }
    interface TxtBoxConfigs {
      c: boolean;
    }
    
    export interface Configs {
      [key: string]: ButtonConfig | FolderConfigs | TxtBoxConfigs;
    }
    
    const config: Configs = {
      buttonConfig: {
        a: "testing"
      },
      folderConfig: {
        b: 1 
      },
      textConfig: {
        c: true 
      },
      anotherConfig: { // error: Type 'number' is not assignable to type 'string'.
        a: 1
      },
      moreConfig: {
        d: "test" // error: Object literal may only specify known properties, and 'd' does not exist in type 'ButtonConfig | FolderConfigs | TxtBoxConfigs'.
      }
    }
    

    Here is the playground example