Типы кортежей в TypeScript имеют фиксированный атрибут length
типа цифра c литерала . (Это было реализовано в microsoft / TypeScript # 17765 ). Таким образом, любая Pair<A, B>
будет иметь длину 2
:
type PairLength = Pair<any, any>['length']; // 2
A generi c ограничение формы R extends Pair<A, B>
означает, что R
должен быть подтипом Pair<A, B>
. В частности, R
должно иметь свойство length
, присваиваемое 2
. Таким образом, вы не сможете присвоить [number, string, boolean]
(чей length
равен 3
) или [number, string, boolean, string]
(чей length
равен 4
) для Pair<A, B>
.
Я бы предложил это. вместо кортежей фиксированной длины вы используете открытые кортежи с конечным остальным элементом . Например:
type PairOrLonger<A, B> = [A, B, ...any[]];
Тип PairOrLonger<A, B>
- это массив длиной 2 или больше, первый элемент которого типа A
, второй элемент типа B
и с нулем или более элементы типа any
после этого. Если вы проверите его, свойство length
будет просто number
(TypeScript не имеет типов диапазона , поэтому вы не можете сказать "по крайней мере 2
" как тип):
type PairOrLongerLength = PairOrLonger<any, any>['length']; // number
Затем мы можем использовать это в foo
, и все работает, потому что у нас больше нет ограничения фиксированной длины на R
:
const foo = <A, B, R extends PairOrLonger<A, B>>(...args: R): R => args;
foo(123, "foo");
foo(123, "foo", true);
foo(123, "foo", true, "bar");
Обратите внимание, что A
и B
не служат цели в foo
, потому что они не выводятся. Вы бы точно так же поступили с такой функцией, как
const bar = <R extends [any, any, ...any[]]>(...args: R): R => args;
bar(123, "foo");
bar(123, "foo", true);
bar(123, "foo", true, "bar");
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код