Bogy
Bogy

Reputation: 21

Typescript generics - use interfaces keys for another key type

It is kinda hard to explain what i want to achieve (not sure if it is possible) so here it the code:

interface CellConfig {
  btn?: cellBtn;
  ...
}
interface CellBtn {
  isEnabled?: boolean;
  label?: string;
  style?: any;
  classes?: any;
}
interface DataSet {
  position: number;
  name: string;
  weight: string;
  symbol: string;
  config?: *missing part, not sure how to do it*
}

so i want to have something like this:

let dataSet: DataSet = {
  position: 1,
  name: 'test',
  weight: '11',
  symbol: '123',
  config: { position: { btn: {isEnabled: true }}, name: { btn: { isEnabled: true }}}
}

basically, config should be optional object and only DataSet keys are allowed (except config) and also each key in config object should be of type CellConfig

Upvotes: 0

Views: 57

Answers (2)

Elias Schablowski
Elias Schablowski

Reputation: 2812

This is a more convoluted way of @jcalz answer that avoids making a new type (though at the cost of readability)

Since you are using interfaces, you can use this to access the full type, then exclude config using Exclude<keyof this, "config"> to get the type sans config, make an object of CellConfigs using Record<keyof Exclude<keyof this, "config">, CellConfig> and make all optional using Partial<Record<Exclude<keyof this, "config">, CellConfig>>:

interface DataSet {
  position: number;
  name: string;
  weight: string;
  symbol: string;
  config?: Partial<Record<Exclude<keyof this, "config">, CellConfig>>;
}

Upvotes: 1

jcalz
jcalz

Reputation: 330086

For ease of constructing DataSet, I'd probably split out the interface into the non-config properties like this:

interface BaseDataSet {
    position: number;
    name: string;
    weight: string;
    symbol: string;
}

And then make DataSet extend it with a mapped config property:

interface DataSet extends BaseDataSet {
    config?: { [K in keyof BaseDataSet]?: CellConfig }
}

You can verify that this behaves as expected for your example.

Playground link to code

Upvotes: 3

Related Questions