very strongly typed `collections/` functions
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]
I think this would be cool. Are you willing to make a PR?
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 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:
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.
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