Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type inference from interface generics

I have an interface that takes two explicit generic parameters:

interface ConnectedComponent<TSelectors, TActions> {
  selectors: TSelectors;
  actions: TActions;
  (props: SelectorProps<TSelectors> & ActionProps<TActions>): any;
}

And here's how I'm using it:

let selectors = { ... };
let actions = { ... };

let Counter: ConnectedComponent<typeof selectors, typeof actions> = props => { ... };
Counter.selectors = selectors;
Counter.actions = actions;

What I would prefer to do would be to infer the generics from the assigned properties:

let Counter: ConnectedComponent = { ... };
Counter.selectors = { ... };
Counter.actions = { ... };

However I don't know how to capture typeof Counter.selectors and typeof Counter.actions inside the interface.

like image 541
Dan Prince Avatar asked Jun 11 '18 14:06

Dan Prince


1 Answers

The only way to do this is to use an extra function and take advantage of the inference behavior of the function. To get inference on the arguments to the function we need to use a function that returns a function approach:

interface ConnectedComponent<TSelectors, TActions> {
    selectors: TSelectors;
    actions: TActions;
    (props: SelectorProps<TSelectors> & ActionProps<TActions>): any;
}

function createConnectedComponent<TSelectors, TActions>(props: { selectors: TSelectors; actions: TActions; }): (fn: (props: SelectorProps<TSelectors> & ActionProps<TActions>) => any) => ConnectedComponent<TSelectors, TActions> {
    return fn => Object.assign(fn, props);
}
let Counter2 = createConnectedComponent({
    selectors: {
        // ...
    },
    actions: {
        // ...
    }
})(p => { /*...*/ }); //p is TSelectors & TActions as expected
like image 68
Titian Cernicova-Dragomir Avatar answered Oct 30 '22 07:10

Titian Cernicova-Dragomir