question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Types for functions like Array.prototype.reduce or RxJS's "scan" seem impossible

See original GitHub issue

Bug Report

I searched, and couldn’t find a related issue (but I find it very unlikely one doesn’t exist). It seems like there should be something labeled “Design Limitation” or the like?

The basic problem is if you’re using a standard “reducer” callback pattern with a seed that is different from what your reducer returns the returned type is incorrect.

// The type of result is `number`, but should be `string`.
const result = [1, 2, 3].reduce((acc, value) => {
//                              ~~~~~~~~~~~~~~~~~
//                                 ^-- Error Here: "No overload matches this call"
    if (acc === null) {
        return '' + value;
    } else {
        return acc + ', ' + value;
    }
}, null);

console.log(result); // "1, 2, 3"
console.log(typeof result); // "string"

🔎 Search Terms

  • is:issue is:open array reduce
  • is:issue is:open reduce callback
  • is:issue is:open reduce "No overload matches this call"
  • is:issue is:open reduce label:"Design Limitation"

🕗 Version & Regression Information

Any version of TS, to TMK. Specifically tested in 4.2 and 4.4.4

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries as best I could. There’s apparently a LOT of them. I didn’t see anything related.

⏯ Playground Link

An example in the playground

💻 Code

// The type of result is `number`, but should be `string`.

const result = [1, 2, 3].reduce((acc, value) => {
//                              ~~~~~~~~~~~~~~~~~
//                                 ^-- Error Here: "No overload matches this call"
    if (acc === null) {
        return '' + value;
    } else {
        return acc + ', ' + value;
    }
}, null);

console.log(result); // "1, 2, 3"
console.log(typeof result); // "string"

🙁 Actual behavior

A type error, even though the compiled JavaScript is valid.

🙂 Expected behavior

No type error, result should be a type string, not number.

Related:

https://github.com/ReactiveX/rxjs/issues/6649

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
DanielRosenwassercommented, Oct 20, 2021

Our inference process is so fundamentally different here, but it does feel bad that when we have plain local statements, we’re able to dive into the body of this loop and know it’s either been set to string or null.

function foo(xs: number[]) {
    let acc = null;
    for (const value of xs) {
        if (acc === null) {
            acc = "" + value;
        }
        else {
            acc = acc + ", " + value;
        }
    }
    return acc;
}

I think at some point, I would like to pick @ahejlsberg’s brain to understand how control flow analysis deals with these sorts of circularities (it’s been a while for me, so I’ve largely forgotten). Maybe we could brainstorm on something that would work better with higher order functions like these. One issue with our inference process is that in our first pass going through arguments, we “lock in” inferences from expressions that aren’t “contextually sensitive” (e.g. callbacks). The null is the only non-contextually sensitive thing here, so it wins. We could play around with tweaks to this process, but

  • it would be more complex
  • it might be a lot more work on every overload
  • it might break a huge chunk of code that exists today
Read more comments on GitHub >

github_iconTop Results From Across the Web

Array.prototype.reduce() - JavaScript - MDN Web Docs
The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value ...
Read more >
Array method definition revamp: Use case collection #36554
I'd like to create a clearinghouse issue here to collect ... Types for functions like Array.prototype.reduce or RxJS's "scan" seem ...
Read more >
reduce - Learn RxJS
Reduces the values from source observable to a single value that's emitted when the source completes. Just like Array.prototype.reduce() ​.
Read more >
Reduce: how and when / Heiker - Observable
Let's talk about the elephant in the Array prototype, the not so loved reduce method but we're not going to discuss whether if...
Read more >
Observable | RxJS API Document - ReactiveX
Creates an Observable from an Array, an array-like object, a Promise, ... static create function, but with different type signature, it was impossible...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found