#Make two function take same parameters but unknown

11 messages · Page 1 of 1 (latest)

supple wyvern
#

Hello I'm trying to make some function that looks like the redux toolkit createSlice.

const commandStore<T>(initial:T, commands: Record<string, Command<T, unknown[]) => {
const actions ={};
Object.entries(commands).forEach(([name, command])=>{
 actions[name] = actionCreator(command.name);
});
return {action}
}

interface Command<T, TParams extends unknown[]> {
 forward(state: T, ...args: TParams): T;
 reverse(state: T,...args: TParams): T
name: string;
}

const actionCreator = <T extends unknown[]>(
command: string): ((...args: T)=>Action) => {
const createAction = (...args: T) => {
  return {command, args}
}
return createAction
}```

I would like each command to have forward and reverse take the same parameters but different command could have different parameters.

I don't know how to define type to be able to return the TParams for each command
eager plume
#
const commandStore = <T>(initial: T, commands: Record<string, Command<T, unknown[]>>) => { }

interface Command<T, TParams extends unknown[]> {
    forward(state: T, ...args: TParams): T;
    reverse(state: T, ...args: TParams): T;
}
#

(not a proper answer, just fixed the few typos in your code)

supple wyvern
#

I think I need some [T keyof commands]: ReturnType<actionCreator<I don't know what>> or something similar but don't know what exactly

supple wyvern
#

This what I come so far:

const commandStore = <T, U extends Record<string, Command<T, unknown[]>>>(
  intialValue: T,
  { name, commands }: { name: string; commands: U },
) => {
  const store = writable(intialValue);
  type ActionType = {
    [K in keyof typeof commands]: Parameters<typeof commands[K]['forward']>;
  };
  const actions: Partial<ActionType> = {};
  Object.entries(commands).forEach(([commandName, command]) => {
    const commandId = `${name}/${commandName}`;
    tracker.register({ name: commandId, store, ...command });
    actions[commandName as keyof typeof commands] =
      actionCreator<Parameters<typeof command['forward']>>(commandId);
  });
  return {
    subscribe: store.subscribe,
    actions: actions as ActionType,
  };
};```
But I still get the error: 
```Type '(state: T, ...args: unknown[]) => Action' is not assignable to type 'Parameters<U[keyof U]["forward"]>'.```
supple wyvern
#

I think I have almost solve it,

type ParametersExceptFirst<T, F> = F extends (state: T, ...args: infer R) => T
 ? R
 : never;

const commandStore = <T, U extends Record<string, Command<T, unknown[]>>>(
 intialValue: T,
 { name, commands }: { name: string; commands: U },
) => {
 const store = writable(intialValue);
 type ActionType = {
   [K in keyof U]: (
     ...args: ParametersExceptFirst<T, U[K]['forward']>
   ) => Action;
 };
 const actions: Partial<ActionType> = {};
 Object.entries(commands).forEach(([commandName, command]) => {
   const commandId = `${name}/${commandName}`;
   tracker.register({ name: commandId, store, ...command });
   const creator =
     actionCreator<ParametersExceptFirst<T, typeof command['forward']>>(
       commandId,
     );
   actions[commandName as keyof U] = creator;
 });
 return {
   subscribe: store.subscribe,
   actions: actions as ActionType,
 };
};
```the only issue left is how to enforce forward and reverse takes the same parameters ?
supple wyvern
#

I Hope the command interface enforce it but it does not work, I have no errrors in reverse declaration

supple wyvern
#

Make two function take same parameters but unknown

slate crown
supple wyvern
rancid yew