robC robC - 12 days ago 5
TypeScript Question

Specify object type for lodash reduce

Lodash

will accept an object, but I get a TypeScript error (commented below) that suggests it's expecting an array. How do I correctly set the types in this example?

interface Fees {
CardHandlingFee: number;
AirlineSurcharge: number;
}

const fees: Fees = {
CardHandlingFee: 2,
AirlineSurcharge: 3
};

let total = 100;

// Argument of type 'Fees' is not assignable to parameter of type 'NumericDictionary'.
// Index signature is missing in type 'Fees'.
total += _.reduce(fees, (sum: number, v: number) => sum + v, 0);

Answer

Unfortunately because you define the type of fees as Fees, it is no longer treated an Object, which would pass the check of NumericDictionary<T> because of TypeScript's structural typing.

So you have two options basically.

1) Remove the type declaration from the fees variable. There is no need for declaring the type anyway. TypeScript will infer the type for you and later when you pass the object somewhere where an instance of Fees is needed, it will pass, because of the structural typing (basically duck typing).

interface Fees {
    CardHandlingFee: number;
    AirlineSurcharge: number;
}

const fees = {
    CardHandlingFee: 2,
    AirlineSurcharge: 3
};

let total = 100;
total += _.reduce(fees, (sum, v) => sum + v, 0);

2) Declare Fees as an extension to NumericDictionary<number>

interface Fees extends _.NumericDictionary<number> {
    CardHandlingFee: number;
    AirlineSurcharge: number;
}

const fees: Fees = {
    CardHandlingFee: 2,
    AirlineSurcharge: 3
};

let total = 100;    
total += _.reduce(fees, (sum, v) => sum + v, 0);

And by the way, you don't need to declare the types of sum and v in the reduce function, that is infered from the type of fees.