Search code examples
javascripttypescriptinterface

TypeScript using "this" keyword in interface


I'm working on a custom interface where I'd like to be able to infer the type of an interface value in its implementation, rather than in the interface definition, without generics. I should add that these implementations will always be object literals and not classes.

Here is what I'm trying to do:

interface Defintion {
  params: unknown; // Should resolve to the type in the implementation
  handler: (dummy: this["params"]) => void; // I want `this` to refer to the implementation, not the interface
}


const customDefn: Defintion = {
  params: { test: "Hello World" },
  handler: (dummy) => {
    // TS Complains here
    console.log(dummy.test)
  }
}

What I want to happen is the type of customDefn.params to resolve to { test: "Hello World" } (so I can get autocomplete in handler) rather than remaining as unknown.

I am aware I can use generics:

interface Defintion<T> {
  params: T;
  handler: (dummy: this["params"]) => void;
}

However, I would then have to define params twice (since I use params programmatically as well):

const customDefn: Defintion<{ test: "Hello World" }> = {
  params: { test: "Hello World" },
  handler: (dummy) => {
    console.log(dummy.test)
  }
}

Which can become cumbersome.


Solution

  • The keyword this can not be used to correlate properties within an object type. You can only use it to get the "static" type of a property.

    In fact, using a stand-alone type, it is not possible to do any cross referencing between properties at all.


    Instead, you can achieve this with a generic helper function.

    interface Defintion<T> {
      params: T;
      handler: (dummy: T) => void; 
    }
    
    function createDefiniton<T>(definiton: Defintion<T>) {
      return definiton
    }
    
    createDefiniton({
      params: { test: "Hello World" },
      handler: (dummy) => {
        console.log(dummy.test)
      }
    })
    

    Playground