how to get return type of map & only give S.
how to get return type of map & only give S.
how to get return type of map & only give S.
how to get return type of map & only give S.
how to get return type of map & only give S.
const state = {
a: 1,
b: 2
}
type StateValue = typeof state
type Getter<S, R, R1> = {
map: (state: S) => R
mapB?: (state: S) => R1
// more ...
}
function getter<S extends Getter<any, any, any>>(
a: S
): ReturnType<S['map']> & ReturnType<S['mapB']> {
return {
...a.map(state),
...a.mapB?.(state)
// more ...
}
}
// to much type
const v = getter({
map: (state: StateValue) => ({
a: state.a
}),
mapB: (state: StateValue) => ({
b: state.b
})
// more map ...
})
// want!! // state will be <{ a: 1, b: 2, c: 1 }>
const v = getter<StateValue>({
map: (state) => ({
a: state.a,
c: state.a
}),
mapB: (state) => ({
b: state.b
})
})
CodePudding user response:
Edit: Updated again in response to updated question
You should accept the state as an additional parameter to getter
, rather than relying on closing over it:
type Fn<Params extends readonly any[] = readonly any[], Result = any> =
(...params: Params) => Result;
type FnMap<S> = Record<string, Fn<[state: S]>>;
declare function getter<S, T extends FnMap<S>>(state: S, map: T): {
[K in keyof T]: ReturnType<T[K]>;
};
const state = { a: 1, b: 2 };
type State = typeof state;
const functions = {
mapA: (state: State) => ({ a: state.a }),
mapB: (state: State) => ({ b: state.b }),
};
const v = getter(state, functions);
v; // { mapA: {a: number}; mapB: {b: number}; }
Edit: Updated in response to updated question
type Fn<Params extends readonly any[] = readonly any[], Result = any> =
(...params: Params) => Result;
type FnMap = Record<string, Fn>;
declare function getter<T extends FnMap, K extends keyof T>(map: T, key: K): ReturnType<T[K]>;
const functions = {
map1: (state: { a: number }) => ({ b: state.a }),
map2: (state: { b: string }) => ({ c: state.b }),
};
const v = getter(functions, 'map1');
v; // { b: number }
You can do it completely with inference. Just move the generic type you were supplying for S
from getter
to the state
parameter in your map
method:
type Getter<S, R> = {
map: (state: S) => R;
};
declare function getter<T extends Getter<any, any>>(value: T): ReturnType<T['map']>;
const v = getter({
map: (state: { a: number }) => ({ b: state.a }),
});
v; // { b: number }