I'm writing a function that takes an optional object options
, itself containing an optional property params
. This options
object has a default value {}
so it can be properly destructured in the function signature.
However, I'm encountring issues when trying to type it with an interface:
type Params = {
params?: { [key: string]: boolean }
}
interface Foo {
(options?: Params): void
};
const myFoo: Foo = ({ params } = {}) => {} // Property 'params' does not exist on type 'Params | undefined'.
The error makes sense: as far as the compiler knows, options
may be undefined (as interpreted by it when a parameter is set as optional), so params
may not exist on it.
However, it doesn't take into account that an optional parameter may have a default value. Yet, I haven't found a way to indicate this properly in a type or an interface. Typing directly in the function signature does work, but this can't be reused or exported.
Is there any standard way to work this out while using a type or an interface?
The type inference for the options
parameter within the parameter list via myFoo: Foo
is Params | undefined
, regardless of whether a default value is provided in the implementation. Only in the body of myFoo
does it infer options
as Params
because of the default value:
// hover over options here: Params | undefined
const myFoo: Foo = (options = {}) => {
// hover over options here: Params
options;
};
To fix it, defer the object destructuring until the type for options
is inferred completely from the implementation's default value:
// no error
const myFoo: Foo = (options = {}) => {
const { params } = options;
};
Or as you've already discovered, you can help the type inference by explicitly typing the parameter as Params
. This carries the potential risk of misinforming the compiler under certain circumstances though:
// no error
const myFoo: Foo = ({ params }: Params = {}) => {};