I have a dataset containing information for a variety of dog breeds, and I am looking to compute the average weight of certain breeds. Each record in the dataset represents a different breed of dog along with their respective weights. The data includes five core breeds that are always present and two additional breeds that may or may not appear:
// TypeScript
type dogSample = {
// 5 core breeds that always appear
bulldog: number,
poodle: number,
pug: number,
chihuahua: number,
boxer: number,
// 2 additional that sometimes appear
dalmatian?: number,
rottweiler?: number, // rottweiler only appears if dalmatian does
// other irrelevant properties
foo: string,
bar: boolean,
baz: number
// and possibly many other unrelated properties
}
The objective is to calculate the average weight of all the dogs based on these specific properties. To achieve this, three functions have been created:
const calcMeanCoreFive = (obj: dogSample) =>
(obj.bulldog + obj.poodle + obj.pug + obj.chihuahua + obj.boxer) / 5;
const calcMeanCoreFivePlusDalmatian = (obj: Required<dogSample>) =>
(obj.bulldog +
obj.poodle +
obj.pug +
obj.chihuahua +
obj.boxer +
obj.dalmatian) /
6;
const calcMeanCoreFivePlusDalmatianPlusRottw = (obj: Required<dogSample>) =>
(obj.bulldog +
obj.poodle +
obj.pug +
obj.chihuahua +
obj.boxer +
obj.dalmatian +
obj.rottweiler) /
7;
Finally, there is a master function that encapsulates all three versions:
const calcMeanDogSample = (obj: dogSample, nBreeds: 5 | 6 | 7) =>
nBreeds === 5
? calcMeanCoreFive(obj)
: nBreeds === 6
? calcMeanCoreFivePlusDalmatian(obj)
// ^
: calcMeanCoreFivePlusDalmatianPlusRottw(obj);
// ^
// argument of type 'dogSample' is not assignable to parameter of type 'Required<dogSample>'
Attempted Solution
To address the issue, an attempt was made to modify the typing within calcMeanDogSample()
using Required<dogSample>
:
const calcMeanDogSample2 = (obj: Required<dogSample>, nBreeds: 5 | 6 | 7) =>
nBreeds === 5
? calcMeanCoreFive(obj)
: nBreeds === 6
? calcMeanCoreFivePlusDalmatian(obj)
: calcMeanCoreFivePlusDalmatianPlusRottw(obj);
This adjustment resolved the error within the function's definition but caused issues when attempting to call calcMeanDogSample2()
with an object of type dogSample
:
const someDogSample = {
bulldog: 24,
poodle: 33,
pug: 21.3,
chihuahua: 7,
boxer: 24,
dalmatian: 20,
foo: "abcd",
bar: false,
baz: 123,
} as dogSample;
calcMeanDogSample2(someDogSample, 6);
// ^
// Argument of type 'dogSample' is not assignable to parameter of type // 'Required<dogSample>'.
// Types of property 'dalmatian' are incompatible.
// Type 'number | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.ts(2345)
Question
Is there an alternative way to define the typing for calcMeanDogSample()
to resolve this issue?
Code can be tested on the TS playground