type-fest icon indicating copy to clipboard operation
type-fest copied to clipboard

ArraySlice not working for optional elements

Open matthias-ccri opened this issue 8 months ago • 6 comments

Bug description

For the use case described in https://github.com/sindresorhus/type-fest/issues/751 --- I'm attempting to use ArraySlice to get a list of trailing function parameters. But, if there's an optional parameter, it doesn't work. The optional parameter is stripped from the tuple.

import type { ArraySlice, ArrayTail } from 'type-fest';

function fn (a: number, b: string, c?: boolean) {}

type params = Parameters<typeof fn>;
//> [a: number, b: string, c?: boolean | undefined]

type tailParams = ArraySlice<params, 1>;
//> [string]
// should be [b: string, c?: boolean | undefined]


// ArrayTail does it correctly:
type tailParams2 = ArrayTail<params>;
//> [b: string, c?: boolean | undefined]

Repro

https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBDAnmApnA3nAglKBDRAZQBtgBjFAGm1wIBU9hi4BfOAMyghDgHIlUAWnYoAzjF4BuAFCz2AVwB2ZGMAiKOGgBR4AXHEXyQAIxRRqx-eKjBFAc2pkA-PuMQIxFHkUBKDC1kBNDA8fBBROABeOAAFULwQFBgzUQAeIIh2TQA+GQB6POy4AG09AyNTczhLOGtbBzhnV3dPbzgAHzglABMUdlsUboBdQOQ0GEZiOLCI6Jx8IlIKVJCZ6gBGXOkCouK6+xGC2oALCHlibuq0Ypr9hqbqlq8NTp6+geHZbbyaBYYmODdCBiODAeBkaBQFAqYiIXTSIIISbTBKiABMUV+9EmK3i4S2OxKtxgNnsjhcjw8zw6XUUvX6ikGQyAA

matthias-ccri avatar Mar 28 '25 20:03 matthias-ccri

I’m not sure if this is a good solution, but changing Array_['length'] to Required<Array_>['length'] seems to be the most cost-effective way to prevent the array’s length from becoming a union type when optional elements are present.

naremloa avatar Apr 01 '25 06:04 naremloa

@naremloa The ArraySlice type need a rewrite, it has a lot of repeated syntax, use old or unnecessary types to do simple tasks.

Image Image Image Image

Also can use UnknownArray instead of readonly unknown[]

@sindresorhus can I take this issue ?

benzaria avatar Jun 08 '25 13:06 benzaria

Sure

sindresorhus avatar Jun 08 '25 23:06 sindresorhus

@benzaria This type has quite a few interesting edge cases, so before diving into a refactor, I’d suggest we first go over the test cases properly.

Also, I have a somewhat working version in my stash, I'll see if I can clean it up and open a PR, maybe you can improve upon that.

There are also a couple of tests that are wrong in the existing test suite. For example, ArraySlice<[1, 2, 3, ...string[]], 1, 5> is expected to return [2, 3, string, string], but that's inaccurate. Because [1, 2, 3] satisfies [1, 2, 3, ...string[]], but [1, 2, 3].slice(1, 5) (i.e. [2, 3]) does not satisfy [2, 3, string, string]. The correct result here should be [2, 3, ...string[]].

som-sm avatar Jun 09 '25 08:06 som-sm

@som-sm True, but I think the example u gave need a little change. I my opinion ArraySlice<[1, 2, 3, ...string[]], 1, 5> should return [2, 3, string?, string?] to satisfies both [2, 3] and [2, 3, 'foo']. because returning [2, 3, ...string[]] is wrong, and Users expect [2, 3, 'foo', 'bar', 'baz'] to throw and error. but in this case it wont.

benzaria avatar Jun 09 '25 11:06 benzaria

because returning [2, 3, ...string[]] is wrong

It's not wrong, it's just less precise. Returning [2, 3, string?, string?] is also fine, it's just that the return value can get too long.


But this is just one example, there are many such edge cases that need proper handling.

som-sm avatar Jun 09 '25 13:06 som-sm