deno_std icon indicating copy to clipboard operation
deno_std copied to clipboard

very strongly typed `collections/` functions

Open scarf005 opened this issue 2 years ago • 3 comments

Is your feature request related to a problem? Please describe.

return type of some of the functions of collections/ functions can be inferred in compile time. inspiration:

  • https://github.com/dilan-dio4/strz
  • https://github.com/type-challenges/type-challenges

Describe the solution you'd like

for example, return type of distinct can be improved with:

type Arr = readonly unknown[]

type Distinct<T extends Arr, Rest extends Arr = []> 
    = T extends readonly [infer Head, ...infer Tail]
        ? Distinct<Tail, Head extends Rest[number] ? Rest : [...Rest, Head]>
        : Rest

function distinct<const T extends Arr>(array: T): Distinct<T> {
    const set = new Set(array);
    return Array.from(set) as Distinct<T>;
}

const d = distinct([1, 1, 1, 2, 'abc', 'abc', 2, 3]) // [1, 2, "abc", 3]
console.log(d) // [1, 2, "abc", 3]

Playground Link

scarf005 avatar May 17 '23 08:05 scarf005

I think this would be cool. Are you willing to make a PR?

lino-levan avatar May 18 '23 20:05 lino-levan

yes. type definitions needs more polishing, however. for example, putting non-readonly array will result in [] for return type when it should be T[]

scarf005 avatar May 18 '23 22:05 scarf005

@scarf005 I think the idea itself has merit, but the types and type utilities need to be very carefully considered and tested on a large variety of inputs and contrived edge cases.

Using the code you provided as an example: it works with the primitives shown, but when object-type values are elements in the input array, you can see bugs appear, because — for one — TypeScript's extends keyword is not the same as JavaScript's same-value-zero equality algorithm used by Set instances:

Forked TS playground

const d = distinct([{ a: 1 }, { a: 1 }, { a: 1, b: 2 }]);
    //^? const d: [{ readonly a: 1; }]

console.log(d); // [{ a: 1 }, { a: 1 }, { a: 1, b: 2 }]

The result objects are also not readonly, etc. It's essential that types accurately represent the runtime values.

Some type testing utilities already exist in std at https://github.com/denoland/deno_std/blob/main/testing/types.ts — you might find them useful in your development if you pursue this.

jsejcksn avatar May 19 '23 09:05 jsejcksn

Though we are open to new type improvement suggestions to std/collections, I'm closing this one as there's no particular action is possible about this for now

kt3k avatar May 08 '24 10:05 kt3k