TypeScript generic type to wrap unsafe 3rd party library loses type-safety

Viewed 16

I have the following piece of code in order to wrap an older 3rd party JS library.

class Parameter<T> {
  private name: string;

  constructor(name: string) {
    this.name = name;
  }

  public set(value: T): Promise<void> {
    return new Promise<void>((resolve, reject) => {
      someLib.setParam(this.name, value, () => resolve());
    });
  }

  public get(): Promise<T> {
    return new Promise<T>((resolve, reject) => {
      someLib.getParam(this.name, value => resolve(value));
    });
  }
}

interface Parameters {
  [key: string]: Parameter<any>;
}

class Config {
  public params: Parameters;

  constructor({ params: Parameters }) {
    this.params = params;
  }
}


function main() {
  const config = new Config({
    params: {
      paramFoo: new Parameter<string>("foo"),
      // ...
    }
  });

  // later in code upon user interaction
  config.paramFoo.set("lorem");  // good :)
  config.paramFoo.set(42);  // no error, bad :(
}

The 3rd party is couple of years old and still uses callback notifications instead of promises. It doesn't care about types at all. I store parameters in an object of generic fields, but have to widen the generics to any so when I finally deal with the parameter objects I am dealing once again with Parameter<any> and thus gaining nothing. Is there some way to narrow the type down to T when I access the parameter?

So far I am using a type name parameter to have at least runtime checks, but I do prefer to catch type mismatches during compilation if possible.

0 Answers
Related