I would like to type a DB insert function that allows defaults: (I am using SetOptional of type-fest)
function defaultInsert<T, D = Partial<T>>(data: SetOptional<T, keyof D>, defaults: D) {
What I am trying to say with the SetOptional is that the data object should contain anything in T, not specified in defaults (D) but it is allowed to overwrite anything in the defaults.
Sadly this is resulting in the following error
Type 'keyof D' does not satisfy the constraint 'keyof T'.
Type 'string | number | symbol' is not assignable to type 'keyof T'.
Type 'string' is not assignable to type 'keyof T'.(2344)
Typescript playground for a more elaborate example.
Is there any way I can filter down the Partial to only contain keys of T since I'm assuming this is the problem due to the possibility of D containing excess properties not in T?
Many thanks
EDIT: As a suggestion from @Alex Chashin, another TS Playground using the keys as a way to define the defaults.
EDIT2: Updated playground with solution provided in UPD2 @Alex Chashin
EDIT3: Updated the previous example so that defaults can also be omitted: playground
UPD2: So the only thing I could come up with, that is not too complicated to exist in this world is this (ts playground):
This passes tests you provided, but unfortunately
{...data, ...default}
is not inferred to beT
, so you have to cast it. I don't think it's a big deal though, as this type cast takes only 4 symbols. The only problem is that you have to explicitly provide keys forD
every time as you need in example writingkeyof typeof personDefaults
UPD: Link to TS playground with one possible solution: playgroungOriginal answer:
So
Partial<T>
already makes all keys ofT
optional, you don't need to useSetOptional
after you didPartial
. In case you want all data keys to be optional just use this:Notice that
defaults
has typeT
, notPartial<T>
, because if it wasPartial<T>
you could provide document that is not complete asdata
and document that is not complete asdefaults
, so merging them would not give a complete document, which could be a problem for you. If it isn't, replaceT
withPartial<T>
, it's hard to judge, because you didn't provide all of the code.If you only want some keys to be optional, do this:
Like this you will only need to provide defaults for optional keys but not for all ones You could also make
defaults
of typeSo that typescript doesn't complain, when you provide defaults for keys that are not optional
then use like