madcapnmckay
madcapnmckay

Reputation: 16004

Empty Mapped Type in Typescript

If I have a generic mapped type that maps keys to functions.

type SomeMappedType<T, R> = {
    [K in keyof T]: (...args: any[]) => R
}

This gets passed to my consuming function via an options type where it itself is optional.

type Options<T = any, R = any, P extends SomeMappedType<T, R> = SomeMappedType<T, R>> = {
    prop1?: P
}

I consume this value and return the output type. In the implementation, if prop1 is undefined it is ignored from the output. However, my Output type returns a non-empty mapped type in this case.

const test2: {
    [x: string]: any;
}

My output type is as follows

type Output<T, R, P extends SomeMappedType<T, R>> = ResolveType<{ [K in keyof P]: ReturnType<P[K]> }>;

Is there a way for the default SomeMappedType<T, R> to express that it effectively contains no keys. I'm looking for the mapped type equivalent of an empty array []

Here is a typescript playground of the problem.

Thanks for any help!

EDIT:

The solution from @spender does work for my original example, which was perhaps too simple. Here is an updated example that show 2 different optional props with different types that both contribute to the Output

Upvotes: 0

Views: 651

Answers (1)

spender
spender

Reputation: 120548

Mapping the any type results in a {[x:string]:...} mapped type, so your problem can be boiled down to this simplified example:

type A = {
    foo: "woo"
}
type M<T> = { [K in keyof T]: T[K] }
type MA = M<A>
//   ^? {foo: "woo";}
type MAny = M<any>
//   ^? {[x: string]: any;}

When there's no type to infer, your generic type T becomes any. Perhaps defaulting it to {} instead of any might be a way forward?

type MEmpty = M<{}>
//   ^? {}

so...

function someFunc<
    T = {}, 
    R = any, 
    P extends SomeMappedType<T, R> = SomeMappedType<T, R>>(
        options: Options<T, R, P>): Output<T, R, P> {
    //...
}

Upvotes: 1

Related Questions