TypeScript: Creating a Dynamic Interface

bob.ts - Nov 29 '21 - - Dev Community

During my time as a developer I've created a lot of "typed" code. One particular issue has come up repeatedly and I finally had a moment of clarity.

The Problem

Whenever I write something like this ...

export interface ConfigType {
  type: string;
}

export interface DataModel {
  config: ConfigType; // ERROR HERE
  [key: string]: string;
}
Enter fullscreen mode Exit fullscreen mode

... I get the following error on the commented line above.

Property 'config' of type 'ConfigType' is not assignable to 'string' index type 'string'.

The issue is that the [key: string]: string; line gets enforced on all key/value pairs on the interface.

I've seen something like the following ...

export interface Person {
  id: number;
  firstname: string;
  lastname: string;
  [key: string]: string | number;
}
Enter fullscreen mode Exit fullscreen mode

... and this code does not present an error. This is because the[key: string]: string; line gets enforced on all key/value pairs on the interface and they are string or number.

I came up with two approaches to solving the issue listed below. I think the first is the better approach, but I will list both for consistency.

The Type Approach

This approach seems much cleaner, creating a new data type that has the fixed and dynamic portions ANDed together.

export interface ConfigType {
  type: string;
}

export type DataModel = {
  config: ConfigType;
} & {
  [key: string]: string;
};
Enter fullscreen mode Exit fullscreen mode

The Union Approach

The following code is another resolution.

export interface ConfigType {
  type: string;
}

export interface DataModel {
  config: ConfigType;
  [key: string]: string | ConfigType;
}
Enter fullscreen mode Exit fullscreen mode

This approach has the "issue" that a new "key" could be used with another ConfigType.

Conclusion

As I said, I think the first approach (the Type Approach) is the better of the two.

If anyone has another or better pattern, please let me know.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .