Reputation: 7786
I am trying to reduce ListAdItemResponse[]
collection to {[name: string]: Date}
type in one of my tests and check that each subsequent published date comes before the current one (e.g. sorted by publishedAt
in descending order):
_.reduce<ListAdItemResponse, {[name: string]: Date}>(
data,
(result, val) => {
expect(new Date(val.publishedAt)).to.be.beforeTime(
new Date(result.publishedAt),
)
return {publishedAt: val.publishedAt}
})
Using TypeScript 2.9.2, I am getting this strange contradictory error ("Expected 2-3 arguments, but got 2"). According to Lodash docs, the third argument is optional, but I can't get past this error no matter what I try. Any idea what may be wrong here? Thanks.
P.S. This compiles without error, but breaks my test, obviously:
_.reduce<ListAdItemResponse, {[name: string]: Date}>(
data,
(result, val) => {
expect(new Date(val.publishedAt)).to.be.beforeTime(
new Date(result.publishedAt),
)
return {publishedAt: val.publishedAt}
}, {}) // with {} added as 3rd argument
Update 9/2/18:
Per @Matt's suggestion, I've tried this approach, but got 3 compilation errors this time. Looks like it's expecting alis.data
collection type to be {[name: string]: Date}
instead of ListAdItemResponse[]
as it is now:
_.reduce<{[name: string]: Date}>(
alis.data, // <-- error 1: Argument of type 'ListAdItemResponse[]' is not assignable to parameter of type '{ [name: string]: Date; } | null | undefined'.Type 'ListAdItemResponse[]' is not assignable to type '{ [name: string]: Date; }'. Index signature is missing in type 'ListAdItemResponse[]'.
(result, val) => { // <-- errors 2,3: Parameter 'result' implicitly has an 'any' type. Parameter 'val' implicitly has an 'any' type.
expect(new Date(val.publishedAt)).to.be.beforeTime(
new Date(result.publishedAt),
)
return {publishedAt: val.publishedAt}
})
Upvotes: 0
Views: 1363
Reputation: 30889
If you want to omit the third argument, then the type of the input items and the accumulator should be the same, so you are expected to pass only a single type argument:
_.reduce<{[name: string]: Date}>(...)
I filed an issue for the contradictory error message.
Even though the number of errors has increased, you are closer to the goal! Assuming the definition of ListAdItemResponse
looks something like this:
interface ListAdItemResponse {
publishedAt: Date;
// other fields...
}
then your call to _.reduce
does not match the overload you intend because ListAdItemResponse
is not assignable to {[name: string]: Date}
because it doesn't have an index signature. (Confusingly, TypeScript's error #1 is based on the incorrect assumption that you want a different overload that is meant for reducing over keys of an object.) There's a special exception for object literal types like the one you are returning from the reducer. What you should probably do is change the state type to {publishedAt: Date}
because that's the only field you're using:
_.reduce<{publishedAt: Date}>(...)
This should make errors #2 and #3 go away too.
Upvotes: 2