Есть ли способ указать, что я хочу тип, который является расширенной версией другого типа?
Мой вариант использования выглядит примерно так:
function times<A extends number, B extends number>(a: A, b: B): A & B;
Идея состоит в том, что эта функция times
сохранит все расширения на A
и B
, но само значение будет изменено на a * b
.
Проблема в том, что если я позвоню times(2, 3)
, я получу тип возврата 2 & 3
, который является неверным и невозможным. Мне не нужно, чтобы оно было 6
, но я определенно не хочу, чтобы оно было 2 & 3
, я хочу, чтобы оно было number
в этом случае.
Расширение типов обычно происходит «автоматически» в Typescript, с различными тайными правилами. Обычно это вызывает у меня головную боль, но на этот раз я хочу этого, но здесь этого не происходит. Во многих подобных обстоятельствах я, конечно, не хотел бы этого, но именно здесь я хочу этого.
Итак, я хочу указать способ возврата WidenedVersionOf<A> & WidenedVersionOf<B>
. Есть ли способ сделать такую вещь?
Некоторое обоснование / ответ на ожидаемое «почему вы просто не используете композицию?»
Да, расширения для типов номеров здесь важны. Мне хорошо известно, что в большинстве случаев «оберточный» объект со значением, хранящимся в виде числа, и расширением, хранящимся отдельно, был бы «лучшим» способом сделать это. Это не в большинстве случаев. На самом деле мы используем фирменные примитивы для единиц измерения (например, секунды, футы). Это означает, что эти расширения фактически существуют только в домене типа и не присутствуют во время выполнения. Это имеет ряд преимуществ для нас.
У нас есть конечное количество брендов (первичные из них In
, Per
и Delta
, поэтому мы можем иметь const v = 20 as number & In<'feet'> & Per<'second'>
или const d = 100 as number & In<'feet'> & Delta
). Функция times
имеет большое количество перегрузок, чтобы охватить все эти случаи. Тем не менее, у нас также есть много универсальных контейнеров, которые хранят номера любого вида брендинга, используя N extends number
. Именно в этом случае возникают проблемы с перегрузкой times
, описанной выше. Невозможно (и, я думаю, невозможно), чтобы каждый из этих универсальных контейнеров обрабатывал отдельно все возможные варианты In
, Per
и / или Delta
, которые могут появиться.