Boivie
Boivie

Reputation: 163

Referencing own property when defining generic type

I'm trying to create a type where the return value of a function depends on the value of another property, is this possible?

As far as I can tell, it's impossible to reference the interface you are defining as you are defining it.

Another approach to this would be saving the keyof T in some kind of type (like K in keyof T or similar) to be reused later in the class, but that doesn't seem to work

This is essentially what I want to do (although this obviously does not work):

interface GenericType<T> {
  column: keyof T;
  genericFunction: () => T[this.column];
}

Let's say T has two keys:

a: number,
b: string

Then I want my generic type to be typed as

column: 'a',
genericFunction: () => number

and if column changes to 'b' then genericFunction should return string.

Upvotes: 1

Views: 163

Answers (1)

Paleo
Paleo

Reputation: 23692

You could do something like this:

interface GenericType<T, U extends keyof T> {
  column: U;
  genericFunction: () => T[U];
}

How to use it:

interface AB {
  a: number
  b: string
}

const a: GenericType<AB, "a"> = {
  column: "a",
  genericFunction() {
    return 12; // the compiler ensures the return value is a number
  }
};

Or, another way to use it with inference:

function makeGenType<T, U extends keyof T>(obj: T, propName: U): GenericType<T, U> {
  return {
    column: propName,
    genericFunction() {
      return obj[propName];
    }
  };
}

const genType = makeGenType({ a: 12, b: "ab" }, "b");
// Type of `genType` is: { column: "b", genericFunction: () => string }

Upvotes: 1

Related Questions