Reputation: 863
Consider the following code...
I would expect the spread operator to be valid code, but it ends up not being so. I'm hoping somebody with expertise in Typescript can advise on why this is...
export default function convertToGlobalFragment<
T extends basicFragmentRecipe_T
>(
fragmentFactory: (recipe: T) => configFragment_I,
recipe: T & { matchingRules: globalMatchingRules_T }
): globalConfigFragment_I {
let {
matchingRules,
...restOfRecipe
}: { matchingRules: globalMatchingRules_T, restOfRecipe: T } = recipe;
}
Property 'restOfRecipe' is missing in type 'basicFragmentRecipe_T & { matchingRules: globalMatchingRules_T; }' but required in type '{ matchingRules: globalMatchingRules_T; restOfRecipe: T; }'.ts(2741)
Upvotes: 0
Views: 54
Reputation: 4010
let {
matchingRules,
...restOfRecipe
}: { matchingRules: globalMatchingRules_T, restOfRecipe: T } = recipe;
This part is wrong because recipe doesn't contain a property called restOfRecipe
- it's { matchingRules: globalMatchingRules_T } & T
- where T
is assignable to basicFragmentRecipe_T
You can pull out restOfRecipe without this code - let TS do the work:
let { matchingRules, ...restOfRecipe } = recipe;
Now restOfRecipe is of type:
Pick<T & { matchingRules: globalMatchingRules_T; }, Exclude<keyof T, "matchingRules">>
Let's break that down.
The type of recipe is the combination of T
and { matchingRules: globalMatchingRules_T; }
To get from this type the properties except 'matchingRules' - we need to exclude matchingRules from T
and { matchingRules: globalMatchingRules_T; }
. As the latter part will always contain matchingRules, we can skip checking the combination and just look at Exclude<keyof T, "matchingRules"
to get the keys of T without 'matchingRules'.
Finally we then use Pick<T, K>
to pick the keys of T
(without matchingRules
) from the type of Recipe
, giving us the result above.
Upvotes: 1
Reputation: 22758
recipe
is basicFragmentRecipe_T
plus { matchingRules: globalMatchingRules_T }
and it seems that basicFragmentRecipe_T
does not have restOfRecipe
prop at all.
You need to indicate the same target type to assign recipe
:
let {
matchingRules,
...restOfRecipe
}: { matchingRules: globalMatchingRules_T } & T = recipe;
Upvotes: 1