News for hackers. Stuff that matters.
Re:TIL: `satisfies` is my favorite TypeScript keyword by chrismorgan on Sunday November 23, 2025 @08:54AM (#46023585)
Here’s the fun part that I suspect many here are forgetting: if you want to write the function body, it will probably (or at the very least can) look very similar!

  function flat() {                        // type FlatArr<Arg extends unknown[]> =
      let [first, ...rest] = this;
      return (this.length > 0) ?           // Arg extends [infer First, ...(infer Rest)] ?
          Array.isArray(first) ?           //   First extends unknown[] ?
              [...first, ...flat(rest)] :  //     [...First, ...FlatArr<Rest>] :
              [first, ...flat(rest)] :     //     [First, ...FlatArr<Rest>] :
          [];                              //   [];
  }
If you want to unternarise it:

  function flat() {
      if (this.length > 0) {
          let [first, ...rest] = this;
          if (Array.isArray(first)) {
              return [...first, ...flat(rest)];
          } else {
              return [first, ...flat(rest)];
          }
      } else {
          return [];
      }
  }
I still wouldn’t call it basic TypeScript, but it’s not conceptually that advanced, you just need to know about infer and extends.

Now in reality, Array.prototype.flat has a more complex definition, partly because (like most of Array’s methods) the method is generic (it works on array-like objects that have a length property and numeric indexing), and partly because of the depth parameter. From lib.es2019.array.d.ts:

  type FlatArray<Arr, Depth extends number> = {
      done: Arr;
      recur: Arr extends ReadonlyArray<infer InnerArr> ? FlatArray<InnerArr, [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth]>
          : Arr;
  }[Depth extends -1 ? "done" : "recur"];

  interface ReadonlyArray<T> {
      // [Snipped: flatMap, and flat’s doc comment]
      flat<A, D extends number = 1>(
          this: A,
          depth?: D,
      ): FlatArray<A, D>[];
  }

  // [And repeated for interface Array<T>.]
Ouch. Don’t like the { done, recur }[Depth extends -1 ? "done" : "recur"] at all, no idea why it wasn’t written as `Depth extends -1 ? Arr : Arr extends ReadonlyArray<…`. And as for hard-coding support for depths up to 20 then bailing… probably pragmatic, it’s possible to support all values, but rather messy: https://stackoverflow.com/q/54243431.
Re:TIL: `satisfies` is my favorite TypeScript keyword by pcthrowaway on Monday November 24, 2025 @03:31AM (#46031671)
Notably, the provided type for Array.prototype.flat doesn't actually provide the flat type for arrays of a known structure.

In other words, if you flatten `[string, [string, number]]` my example would give you `[string, string, number]` whereas the one in lib.es2019.array.d.ts would give you `(string | number)[]`

(my example, on the other hand, would only flatten a depth of 1, though a completely flattened type instead of just depth 1 could be represented by changing `[...First, ...FlatArr<Rest>] :` to `[...FlatArr<First>, ...FlatArr<Rest>] :`

I haven't tried supporting a depth param, but I suspect it's possible.