I created a bug report for this, but perhaps someone has an idea for a workaround. Basically I want to have some arguments to a function based conditionally on the type of another:
declare function foo<P>(params: { f: (p: P) => void } & P): void;
foo({
f(params: { bar(x: number): void }) {},
bar(x) {},
});
So there is a special parameter f
which has a function type, and whatever properties that function expects must be included as arguments to foo
. Here again the parameter to bar
is inferred as any
but should be number
.
Whenever I see a requirement to have function type that depends on argument values, "use overloads" is the first thing that comes to mind:
declare function foo(params: { tag: 'a', bar(x: number): void }): void;
declare function foo(params: { tag: 'b', bar(x: boolean): void }): void;
foo({ tag: 'a', bar(x) { console.log('x =', x)} }); // (parameter) x: number
Update I assume that in the following code foo
and f
are React components, and foo
exposes f
as its property, as well as all the properties that f
has.
declare function foo<P>(params: { f: (p: P) => void } & P): void;
foo({
f(params: { bar(x: number): void }) {},
bar(x) {},
});
There is a way to rewrite it, it you don't insist that the name of f
(which is a property of foo
), as well as types of f
properties must be declared inline within foo
arguments when calling it.
You can declare a type that describes properties of such composed component, it takes two generic parameters: the type of inner component properties, and the name of inner component in outer properties:
type ComposedProps<InnerProps, N extends string> =
InnerProps & { [n in N]: (props: InnerProps) => void };
// Also I assume in reality it does not return `void` but `React.Element`,
// but I don't think it matters
declare function foo<P>(params: P): void;
// foo generic parameter is given explicitly,
// which allows to infer (and not repeat) parameter types for `f` and `bar`
foo<ComposedProps<{bar(x: number): void}, 'f'>>({
f(params) {}, // params: { bar(x: number): void; }
bar(x) {}, // (parameter) x: number
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With