# Array.prototype.mapNotNull

**URL:** <https://es.discourse.group/t/array-prototype-mapnotnull/2441>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [October 4, 2025, 1:39pm UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441 "2025-10-04T13:39:08Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [October 14, 2025, 8:15pm UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/21 "2025-10-14T20:15:39Z")

</div>

> [@bakkot](#):
>
> `filterMap`, like it is in most other languages.

But no other language lets you pick the value. I'm prepared to be convinced, I just find it interesting that the pattern appears to have no precedent in any other mainstream language. So using a different name may help signify the difference. That said, I agree that someone searching for this is likely to use the terms map and filter.

I appreciate the time series use case, I can buy that.

> [@bakkot](#):
>
> But I also want to push back on the general line of thinking. We’re making a general-purpose programming language. It should be general purpose. Assuming that a particular kind of value will never arise

I'm not saying it will never arise. I'm coming at this from an angle of how intuitive the code would be when someone reads it for the first time. How likely they will make the right guess of what the method does. The explicitness of the Kotlin name appeals to me in this regard, even if it means that some use cases would need to use .map and .filter or .flatMap. It may be that I am under estimating how intuitive the arbitrary ignored value pattern is and over valuing Kotlin's name.

---

<div class="post-metadata">

**Author:** ![bakkot](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bakkot/32/22_2.png) [@bakkot](https://es.discourse.group/u/bakkot)\
**Post date:** [October 14, 2025, 8:54pm UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/22 "2025-10-14T20:54:46Z")

</div>

> [@aclaymore](#):
>
> But no other language lets you pick the value. I'm prepared to be convinced, I just find it interesting that the pattern appears to have no precedent in any other mainstream language.

In most languages you can cheaply and idiomatically use an Option or something similar to achieve the same thing. We can’t, so we’ve got to work with what we have.

I don’t think it’s actually important to signify the difference - it’s accomplishing the same thing, in _almost_ the same way, just with minor accommodations for language-level differences. The important thing is, what do you reach for when you have a problem of this shape? And the answer is that you reach for `filterMap`, no matter what language you’re using, and then the question of exactly how you _use_ that thing will depend on details about the language. Or conversely, as a reader of code, seeing `filterMap` is on its own sufficient to tell you what the problem being solved is, and then you can look at the details of how it’s being used and how it works in this particular language if you need that level of resolution.

> [@aclaymore](#):
>
> I'm not saying it will never arise. I'm coming at this from an angle of how intuitive the code would be when someone reads it for the first time.

I think the optional parameter will be pretty niche, so people who are encountering it for the first time will probably have to look it up. I’m OK with that; in the absence of named parameters, that’s usually what happens. For the common case where you don’t need the optional parameter, I think it will be obvious enough.

That said I think in a lot of cases it will still be pretty clear even with the optional parameter:

```typescript
let skip = {};
return list.filterMap(x => x.isValid ? x.value : skip, skip);

```

or in the case that the values are known to be non-negative numbers if not null you can do something like

```typescript
return list.filterMap(x => x.isValid ? x.value : -1, -1);

```

or whatever. I think for many readers just seeing that this is `filterMap` would be enough to figure out what’s going on here.

* * *

Even leaving aside the question of whether to take the optional parameter, I really think we should go with the common name for this and not Kotlin’s bespoke name. There’s a lot of value in using the common names for things.

(… Again, if browsers are even willing to try shipping this, under any name.)

---

<div class="post-metadata">

**Author:** ![tabatkins](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/tabatkins/32/170_2.png) [@tabatkins](https://es.discourse.group/u/tabatkins)\
**Post date:** [October 14, 2025, 9:41pm UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/23 "2025-10-14T21:41:23Z")

</div>

I also strongly agree with the `filterMap` naming over `mapNotNull`, for different reasons. `mapNotNull` suggests it maps over the non-null values, but since `map` doesn’t change the length of the list, presumably those null values just stay in the result, unchanged. `filterMap` is very clear about what’s happening - there’s a filter and a map, and `filter` _does_ remove items and change the length of a list. Very straightforward to understand.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [October 15, 2025, 2:28am UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/24 "2025-10-15T02:28:11Z")

</div>

> [@bakkot](#):
>
> In most languages you can cheaply and idiomatically use an Option or something similar to achieve the same thing. We can’t, so we’ve got to work with what we have.

JS is not alone in this. The other languages that don't have an option pattern chose to hard code which value(s) gets filtered out. Not saying we can't innovate, Im just triple checking we are improving on these earlier designs. It does sound like there are good reasons to do something slightly novel here.

> [@tabatkins](#):
>
> `mapNotNull` suggests it maps over the non-null

Then it is the case that I was over valuing the clarity of that name and concede to `filterMap` being the better name.

---

<div class="post-metadata">

**Author:** ![AlexanderKaran](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/alexanderkaran/32/2541_2.png) [@AlexanderKaran](https://es.discourse.group/u/AlexanderKaran)\
**Post date:** [October 16, 2025, 11:06am UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/25 "2025-10-16T11:06:58Z")

</div>

@tabatkins raises a good point about `filterMap` having clearer intent. The other angle to consider is that `mapNotNull` is clearer in Kotlin because it does not have to deal with `undefined`. There is only `null`. In JS land, `mapNotNull` could be interpreted as:

- Removes `null` only
- Remove `null` and `undefined`
- Removes `null`, `undefined`, and empty string
- Removes all falsy values

Not saying these are correct, but common ways people could interpret this in the JS world.

Following your train of thought, @aclaymore, that filtering out `null` is the most common pattern, I agree, hence this started out as `mapNotNull`. However, after the discussion, we are moving towards the name `filterMap`. I find it inconsistent that `filterMap`would only take a map function and filter out `null` only. The name `filterMap` strongly implies configurable filtering behavior, like its namesake `filter`

I think if you go with `filterMap`, it makes far more sense to pass the value in. @bakkot said people can look it up when they encounter it. While developers can look up unfamiliar methods, I wonder if, by defaulting to `null`, we make this more likely by not having the value parameter.

---

<div class="post-metadata">

**Author:** ![ptomato](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ptomato/32/214_2.png) [@ptomato](https://es.discourse.group/u/ptomato)\
**Post date:** [October 19, 2025, 5:20pm UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/26 "2025-10-19T17:20:17Z")

</div>

> [@AlexanderKaran](#):
>
> Transforming arrays while filtering out null/undefined values with a single call is a common pattern in modern languages, but JavaScript requires chaining, reduce or for loops:
> 
> ```javascript
> // Option 1: Chaining
> const emails = users
> .map(user => user.email)
> .filter(email => email != null);
> 
> ```
> 
> […quote abridged…]
> 
> Benefits:
> 
> - Single pass, no intermediate array
> - Clear declarative intent
> - Better performance characteristics (depends, not really the main benefit)

I’ll note that iterators also provide a single pass without intermediate array, clear declarative intent, and better performance characteristics, and they already exist in the language:

```javascript
const emails = users.values()
  .map(user => user.email)
  .filter(email => email !== null)
  .toArray();

```

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [October 23, 2025, 9:09am UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/27 "2025-10-23T09:09:19Z")

</div>

> [@AlexanderKaran](#):
>
> I think if you go with `filterMap`, it makes far more sense to pass the value in. @bakkot said people can look it up when they encounter it. While developers can look up unfamiliar methods, I wonder if, by defaulting to `null`, we make this more likely by not having the value parameter.

The problem with `filterMap` is that the name comprises two existing operations. `filter` takes a callback, `map` takes a callback, does `filterMap` take two callbacks? Does the filter run on the input, or the output? Filtering input would be useful in situations where the `mapFn` is expensive, but existing `flatMap` suggests the mapping’s done first, then the flattening/filtering. On the other hand, if filtering output, writing a callback seems unnecessarily verbose. Besides, both filter-then-map and map-then-filter use cases with two callbacks are already covered by iterators.

That leaves us with the use case of `map` first, then discard unwanted values. I think it’d be better to avoid having `filter` in the name. From prior art listed above `compactMap(mapFn, [unwanted])` looks reasonable. And it should remove `undefined` by default, because that’s what a missing argument is.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [October 24, 2025, 4:31pm UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/28 "2025-10-24T16:31:29Z")

</div>

That's not a problem; `flat` and `map` both take callbacks, and `flatMap` also takes a callback.

Indeed, just like `flatMap`, `filterMap` would have to do the map first, and then the filter.

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [October 24, 2025, 7:49pm UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/29 "2025-10-24T19:49:11Z")

</div>

> [@ljharb](#):
>
> `flat` and `map` both take callbacks

`flat` doesn’t. The problem I was alluding to is that `filter` already means filter-by-predicate in JS; and the operation that does `map` and then prune-by-value (i.e. something other than `filter`) shouldn’t be named `filterMap`.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [October 24, 2025, 8:45pm UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/30 "2025-10-24T20:45:49Z")

</div>

oh lol true, good call

---

<div class="post-metadata">

**Author:** ![AlexanderKaran](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/alexanderkaran/32/2541_2.png) [@AlexanderKaran](https://es.discourse.group/u/AlexanderKaran)\
**Post date:** [November 2, 2025, 8:25am UTC](https://es.discourse.group/t/array-prototype-mapnotnull/2441/31 "2025-11-02T08:25:47Z")

</div>

Valid points, however, I am not sure I like `compactMap` either. What does `compact` really mean when conjointed with `map`? To me, no idea. I would have to look this function up; however, there's nothing wrong with that.

[Previous page](https://es.discourse.group/t/array-prototype-mapnotnull/2441.md?page=1)
