简体   繁体   中英

How to type a property in a interface according to keys of another property has unknown structure in TypeScript?

I used a module can do such thing

function print(obj, key) {
  console.log(obj[key])
}

print({'test': 'content'}, '/* vs code will show code recommendation when typing */')

I want to have this feature but I forgot the name of the module and I even don't sure if I misremembered (maybe it's impossible).

I'm working on a package and have a code like this:

interface Box {
  content: {
    [key: string]: string
  }
  using: string // key of content 
}

const box: Box = {
  content: {
    'something': 'inside'
  },
  using: 'something'
}

function showBox(box: Box) {
  console.log(box.content[box.using])
}

Actually the content is a object comes from another package using typescript. I would like not to wrap the type if possible.

To help devs can find bugs during coding, I'm looking for if there is a way to check invalid Box type like:

const box: Box = {
  content: {
    'something': 'inside'
  },
  using: 'samething' // raise error when checking type
}

Or any way can make code recommendation of IDE know the using should be a key of content object.

My code currently looks like this but it's not what I want, and I don't have any idea to go on

interface Box {
  content: {
    [key: string]: string
  }
  using: keyof Box['content'] // will be string | number
}

Thanks to all response

Your solution is actually correct, but IDE cannot suggest you anything because keyof Box['content'] is typed to be an arbitrary string. If you know that content should always have some specific structure, you can just put it inside Box description like this:

interface Box {
  content: {
    something: string;
  };
  // now it only allowed to be 'something', and IDE will suggest it
  using: keyof Box['content'];
}

If your content 's type is actually a parameter (meaning that you can have boxes for arbitrary types), you should make it a parameter for Box interface, thus making it a generic interface:

interface GenericBox<T> {
    content: T;
    using: keyof T;
}

Now you can use it like this:

// simple example interface to fill a box
interface TestContent {
    x: string;
    y: number;
}

const genericBox: GenericBox<TestContent> = {
    content: {x: '', y: 0},
    using: 'x', // now it can be only 'x' or 'y', and IDE will suggest it
};

Check it out on the playground .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM