Search code examples
typescripttypescript-genericsreact-typescript

Generic interface inferring type from object property


I've got an interface I with the goal of making sure that the property type of val is the same as the return type of fn.

The type in question is restricted to string or number.

interface I<T extends string | number> {
  val: T;
  fn: () => T;
}

const x1: I<string> = {
  val: "hello",
  fn: () => "world",
};

const x2: I<number> = {
  val: 3,
  fn: () => 4,
};

Is it somehow possible to not having to explicitly set T and rather infer it? So that I could just do:

// accepted
const x1: I = {
  val: "hello",
  fn: () => "world",
};

// accepted
const x2: I = {
  val: 3,
  fn: () => 4,
};

// rejected
const x3: I = {
  val: "hello",
  fn: () => 4,
};

// rejected
const x4: I = {
  val: 3,
  fn: () => "world",
};


Solution

  • As far as I know, it is not possible for TS to infer the type for your example. However, there is a way to achieve similar effects using a helper function:

    function make<T extends string|number>(input: I<T>) {
      return input;
    }
    
    // accepted
    const x1 = make({
      val: "hello",
      fn: () => "world",
    });
    
    // accepted
    const x2 = make({
      val: 3,
      fn: () => 4,
    });
    
    // rejected
    const x3 = make({
      val: "hello",
      fn: () => 4,
    });
    
    // rejected
    const x4 = make({
      val: 3,
      fn: () => "world",
    });
    

    Playground link