In my coding dilemma, I encountered an issue with a function designed to work with callbacks and input objects. The initial function matches the input object's "type" property with a key in the callbacks object and calls the corresponding callback. Now, I'm striving to create a higher-order function that takes the callbacks object as input and returns a function for handling matching input objects. However, upon calling the returned function, TypeScript throws an error, claiming the input object is not assignable to a never type.
type Actor <K extends string, T> = (input: { type: K } & T) => void
type Actors <K extends string, T> = { [Key in K]: Actor<K, T> }
type TfromA<K extends string, A extends Actors<K, any>> =
A extends Actors<K, infer T> ? T : never
export function marion<
K extends string,
A extends Actors<K, TfromA<K, A>>,
> (
actors: A,
input: { type: K } & TfromA<K, A>
): void {
const actor = actors[input.type]
actor(input)
}
interface Alpha { type: 'alpha', count: number }
interface Beta { type: 'beta', label: string }
const alphaBeta = {
alpha: (input: Alpha) => console.log(input.count),
beta: (input: Beta) => console.log(input.label)
}
const alpha: Alpha = { type: 'alpha', count: 42 }
marion(alphaBeta, alpha) // No errors
function higher<
K extends string,
A extends Actors<K, TfromA<K, A>>,
> (
actors: A
): (input: TfromA<K, A> & { type: K }) => void {
return function (input: TfromA<K, A> & { type: K }): void {
marion(actors, input)
}
}
const lower = higher(alphaBeta)
lower(alpha)
// Argument of type 'Alpha' is not assignable to parameter of type 'never'.
// The intersection 'Alpha & Beta & { type: string; }' was reduced to 'never' because property 'type' has conflicting types in some constituents.ts(2345)
I am seeking a solution to create a flexible and reusable function capable of handling various sets of callbacks and input objects while facilitating the creation of higher order functions effortlessly.
Check out the Playground: https://tsplay.dev/w2844m