I have a function that needs to convert a dictionary of functions with partially dynamic properties into a new dictionary of functions with similar properties.
What I have so far:
interface Dictionary<T extends any> {
[key: string]: T
}
type InputFunction<T> = (value: T, parameters?: any) => T
type InputFunctionMap<T> = Dictionary<InputFunction<T>>
type OutputFunction = (parameters?: any) => void
type OutputFunctionMap<T, U extends InputFunctionMap<T>> = {
[P in keyof U]: OutputFunction
}
function create<T>(key: string, value: T): [() => T, (value: T) => void]
function create<T, U = InputFunctionMap<T>>(key: string, value: T, inputs: U): [() => T, Readonly<OutputFunctionMap<T, U>>]
function create<T, U = InputFunctionMap<T>>(key: string, value: T, inputs?: U): [() => T, (value: T) => void] | [() => T, Readonly<OutputFunctionMap<T, U>>] {
// ...
}
What I'm trying to accomplish:
const [getFoo, updateFoo] = create('foo', 'FOO')
getFoo() // => 'FOO'
updateFoo('foo') // => 'foo'
getFoo() // => 'foo'
interface MathParameters {
operation: 'MULTIPLY' | 'DIVIDE'
operand: number
}
const [getBar, {addToBar, addSevenToBar, applyMathToBar}] = create('bar', 0, {
addToBar: (value, parameters: number) => value + parameters,
addSevenToBar: (value) => value + 7,
applyMathToBar: (value, parameters: MathParameters) => {
switch (parameters.operation) {
case 'MULTIPLY':
return value * parameters.operand
default:
return value
}
}
})
getBar() // => 0
addSevenToBar()
getBar() // => 7
addToBar(3)
getBar() // => 10
applyMathToBar({operation: 'MULTIPLY', operand: 2})
getBar() // => 20
The problem is that I can't figure out how to properly and generically type parameters (I don't want them to be any) so that the type can be inferred from the input function and be correctly available as the parameter in the output function.
Update:
Thank you for the support so far!
I'm just having trouble getting the ouput mapping to work as intended: Typescript Playground
type TailParams<T> = T extends (arg: any, ...args: infer A) => void
? A
: never
const input = inputs[name as keyof U]
outputs[name as keyof U] = (...args: TailParams<typeof input>) => {
//
}
Throws: Type '(...args: TailParams<U[keyof U]>) => void' is not assignable to type 'TailFunc<U[keyof U]>'.