0

I have one Basic interface:

interface Basic {
  [key: string]: {
    data: string;
  };
}

Another interface extending it:

interface Another extends Basic {
  'onekey': OneKeyData;
  'secondkey': SeconKeyData;
}

My issue with is when use generic T extends keyof Another it allows any string keys because of Basic interface. OneKeyData and SecondKeyData they all contain data property as in Basic. I would remove extends Basic if it wasn't used in other place like this:

interface Options<TKey extends keyof Another> {
  field: Another[TKey]['data'];
}

What is the best solution in this case? Is it possible to get keyof only Another interface?

realplay
  • 2,078
  • 20
  • 32
  • 1
    Your definition of `Options` is currently redundant, since `Another[TKey]['data']` always evaluates to `string` right now. Are there instances in your actual code where this is not the case? – Christian Ivicevic May 30 '19 at 23:13
  • Furthermore do you really need `Basic`? It might be possible that you can replace you entire data structures with just `Record` as indicated by your snippets thus far. – Christian Ivicevic May 30 '19 at 23:18
  • I don't understand what your use case is, but if you're looking for a way to get the known keys of an interface (that is, without the `string`), [you can do it](https://stackoverflow.com/a/51955852/2887218). If that's what you want I'd be inclined to close this as a duplicate. Otherwise please explain clearly what you're trying to accomplish. – jcalz May 31 '19 at 00:39

1 Answers1

4

As mentioned in the comments, it is possible to get keyof ignoring the index signature using a trick with conditional type inference.

type KnownKeys<T> = {
    [K in keyof T]: string extends K ? never : number extends K ? never : K
} extends { [_ in keyof T]: infer U } ? U : never;

type KnownKeysOfAnother = KnownKeys<Another> // "oneKey" | "secondKey";

Is that what you're looking for?

jcalz
  • 264,269
  • 27
  • 359
  • 360