Одна проблема, которую вы хотите решить при решении этой проблемы, это тип входного объекта _sources
. На вашей ссылке TS Playground она в настоящее время набирается как:
const _source: {
foo: { type: Types; };
bar: { type: Types; };
};
Обратите внимание, что параметры type
устанавливаются на Types
вместо конкретного Types.Color
или Types.Number
.
В Typescript 3.4 вы можете исправить это, добавив as const
после определения:
const _source = {
foo: { type: Types.Color },
bar: { type: Types.Number },
} as const;
или, до версии 3.4, вы можете использовать Types.Color as Types.Color
, чтобы получить машинописный текст для обработки их как литеральных значений.
После того, как это будет очищено, Mapped Type получит необходимое вам возвращаемое значение. Я написал это как универсальный вспомогательный тип.
type ConvertedSources<T extends Record<string, SourceValue<any>>> = {
[key in keyof T]: ValuesByType[T[key]['type']]
};
Если вы передадите typeof _source
этому, вы увидите, как каждое свойство в _source
будет сопоставлено с соответствующим типом значения на основе вашего интерфейса ValuesByType
.
Затем вам просто нужно заставить свою функцию использовать это в своей сигнатуре, сохраняя то же ограничение типа:
function convert<
TSources extends Record<string, SourceValue<any>>
>(source: TSources): ConvertedSources<TSources> { ... }
Обратите внимание, что вам также необходимо привести результат вашего reduce()
вызова к ConvertedSources<TSources>
или изменить часть внутреннего кода, чтобы сохранить типы.
TS Playground Demo