VSDekar
VSDekar

Reputation: 1821

Infer Parameter Type of a Function

I would like to infer the type of a parameter in Typescript but was not lucky until yet.

I have the following Code

// is it possible to find out the type of the payload parameter?
type Dispatch<T> = (prop: keyof T, payload?: any) => any; 

class TestClass<T> {
  obj: T;
  dispatch: Dispatch<T> = (prop, payload) => {
    const func = this.obj[prop];
    return (func as any)(payload);
  };

  constructor(obj: T) {
    this.obj = obj;
  }
}

interface SomeFuncs {
  foo(payload: string): string;
  bar(payload: number): string;
}

const someFuncs: SomeFuncs = {
  foo(payload) {
    return 'Hello ' + payload;
  },
  bar(payload) {
    const result = 10 + payload;
    return 'Your result is ' + result;
  },
};

const testClass = new TestClass(someFuncs);
const result = testClass.dispatch('bar', 'bla'); // I would like to get here an error because the payload for bar should be of type number
console.log(result);

Is it somehow possible to infer the type for payload in the Dispatch<T> type? I played around with the Parametersstuff which was added in 2.8 but still have no clue how to solve it.

The key on the other hand works just fine. So since i have the Base Type T and the key i thought it should be possible to find out the type of the parameter.

Upvotes: 2

Views: 103

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249546

Dispatch would have to be a generic function (not just a generic type) to be able to capture the actual type of the argument passed in and use this to get the corect parameters from T

// is it possible to find out the type of the payload parameter
type Dispatch<T extends Record<keyof T, (...a: any[]) => any>> = <K extends keyof T>(prop: K, ...payload: Parameters<T[K]>) => any; 

class TestClass<T extends Record<keyof T, (...a: any[]) => any>> {
    obj: T;
    dispatch: Dispatch<T> = (prop, ...payload) => {
        const func = this.obj[prop];
        return func(...payload);
    };

    constructor(obj: T) {
        this.obj = obj;
    }
}

interface SomeFuncs {
    foo(payload: string): string;
    bar(payload: number): string;
}

const someFuncs: SomeFuncs = {
    foo(payload) {
        return 'Hello ' + payload;
    },
    bar(payload) {
        const result = 10 + payload;
        return 'Your result is ' + result;
    },
};

const testClass = new TestClass(someFuncs);
const result = testClass.dispatch('bar', 'bla'); // err
const result2 = testClass.dispatch('bar', 0); // ok
console.log(result);

Note: solution is Typescript 3.0 and above

Upvotes: 3

Related Questions