Let's say I've got a function that expects a certain interface
interface Foo {
foo: number;
bar: number;
baz?: number;
buz?: number;
}
const doFoo = (params: Foo) => { /* ... */ };
I also have some constant that contains default values for a subset of Foo
:
const BASE_PROPERTIES = {
foo: 42,
baz: 9001,
};
doFoo({
...BASE_PROPERTIES,
bar: -1000
});
This works fine. But I'm wondering if there's a way that I can signify that BASE_PROPERTIES
contains some parts of Foo
. Both to provide intellisense when editing, and make it clear what the constant is used for. Essentially an automated Pick<>
.
I could do
const BASE_PROPERTIES: Partial<Foo> = { /* ... */ }
However that will mean that using it in the spread gives an error for foo
because Type 'number | undefined' is not assignable to type 'number'
. I could as any
or as Foo
it, but that trades convenience for risk in the event that I actually forgot to include foo
.
Likewise, I could use pick
const BASE_PROPERTIES: Pick<Foo, 'foo' | 'baz'> = { /* ... */ }
But that requires me to keep it updated as I go (a bit cumbersome, not particularly DRY for very large objects), and won't give me intellisense as I'm adding further properties, kind of defeating half the point of adding it in the first place.
Is there a way to hint to typescript, that an object should follow the schema of an interface, but that it should figure out how the const actually fits the interface?
CodePudding user response:
You are looking for the satisfies
operator introduced in Typescript 4.9
const BASE_PROPERTIES = {
foo: 42,
baz: 9001,
} satisfies Partial<Foo>
This will make sure that BASE_PROPERTIES
satisfies the type Partial<Foo>
while still inferring the literal type.
CodePudding user response:
I guess you can have a small utility function to do so. Something like
function createBaseProps<K extends keyof Foo>(props: Pick<Foo, K>) {
return props
}
you should get intellisense and type checks
const BASE_PROPERTIES = createBaseProps({
foo: 123,
})
and be able to merge the result with your doFoo
example