For a while now, I've been working on getting these types to function properly. My main focus is on fixing the types rather than the implementation itself. The function in question takes and reduces over the config array using the fn
property. Each item in the config should have the aggregated return type from the previous steps' fn
function. The types seem to be correct, however, the autocomplete feature in my editor breaks when adding a new object to the array. TypeScript Server mistakenly identifies it as an array type. Is there a way to resolve this issue?
Here is the code:
// interfaces
interface Config<T extends object, R extends object> {
fn: (state: T) => R
bro?: boolean
}
interface OverloadRunner {
<A extends object = object, B extends object = object>(
configArray: [Config<A, B>],
): void
<
A extends object = object,
B extends object = object,
C extends object = object,
>(
configArray: [Config<A, B>, Config<A & B, C>],
): void
<
A extends object = object,
B extends object = object,
C extends object = object,
D extends object = object,
>(
configArray: [Config<A, B>, Config<A & B, C>, Config<A & B & C, D>],
): void
// extend for further items
}
// function
const overloadRunner: OverloadRunner = (steps: Config<any, any>[]) => {
let accumulator = {}
for (const step of steps) {
const result = step.fn(accumulator)
accumulator = {
...accumulator,
...result,
}
}
}
// Usage example
overloadRunner([
{
fn: (state) => {
return { now: 'here' }
},
bro: false,
},
{
fn: (state) => {
return { next: 'step' } // state type correctly inferred as { now: string }
},
bro: false,
},
{
// does not autocomplete here. TS Server thinks it's an array
}
])
Screenshot showing incorrect autocomplete: vscode type autocomplete
I attempted to move the generic declarations to the entire interface instead of the overloads, but doing so compromised the piping aspect of the state
argument.
interface OverloadRunner<
A extends object = object,
B extends object = object,
C extends object = object,
D extends object = object,
> {
(configArray: [Config<A, B>]): void
(configArray: [Config<A, B>, Config<A & B, C>]): void
(configArray: [Config<A, B>, Config<A & B, C>, Config<A & B & C, D>]): void
}
I also experimented with some tuple utility types, but they too failed to fix the autocomplete issue.
type StepsArray<
T extends any[],
R extends object = RequestPropertiesAndHelpers,
> = T extends [infer First extends object, ...infer Rest]
? [Step<R, First>, ...StepsArray<Rest, R & First>]
: []