Home > Software engineering >  Typescript narrow down types in existing classes
Typescript narrow down types in existing classes

Time:02-18

I'm currently using an existing package that has a type MyType defined

export type MyType<T = unknown> = (params: {[k: string]: any}) => T;

This type is implemented in the constructor of a class.

export class MyClass<T = unknown> {
  constructor(
    id: string,
    value: T | MyType<T>,
    options?: any,
  );
}

What I would like to do is to create a class extending the MyClass class with more specific values for the params parameter in the MyType type:

type MyNewType = {
  param1: number;
  param2: number;
}
const myVar = new MyClass('exampleId', async (params: MyNewType) => { 
  return params.param1 * params.param2 
}

However, typescript (correctly) complains that the types are not compatible, since MyNewType has REQUIRED keys, while the {[k: string]: any} type doesn't have any required keys. I could solve the error by simply using Partial<MyNewType> instead of MyNewType, but then I have to do all sorts of type-checking inside the function itself. Changing the definitions of MyType and MyClass are also not possible.

My question is: How can I use (or extend) MyClass so that I can give more specific types to the params parameter and I don't have to do extra type checking inside my function.

CodePudding user response:

You can make params a generic too:

export type MyType<T = unknown, Params extends Record<string, any> = Record<string, any>> = (params: Params) => T;

type MyNewType = {
  param1: number;
  param2: number;
}

export class MyClass<T = unknown> {
  constructor(
    id: string,
    value: T | MyType<T, MyNewType>,
    options?: any,
  ) { };
}

CodePudding user response:

Could narrowing it down like that work for you ?

const myVar = new MyClass('exampleId', (params) => {
    if ("param1" in params && 'param2' in params) {
        return params.param1 * params.param2
    }
    return 0; // or whatever other default value 
});
  • Related