#typescript #typescript-typings #typescript-generics
Вопрос:
Я хотел бы иметь возможность преобразовать массив строк в словарь, где переданные строки становятся ключами объекта (и значение равно true
).:
// obj = { foo: true, bar: true );
const obj = toObject("foo", "bar");
Это очень просто во время выполнения с JS, но я хочу, чтобы типы сохранялись в TS, и это удивительно сложно. Вот реализация, которая работает во время выполнения, но в конечном итоге выводит объект с типом . all
Фу.
function toObject<T extends readonly string[]>(...keys: T) {
return keys.reduce((acc, k) => {
acc[k] = true;
return acc;
}, {} as any);
}
При all
этом мы остаемся с нулевым значением, но это все равно почти лучше, чем не указывать as any
в редукторе. По крайней мере, мы можем индексировать словарь во время выполнения. Если бы мы оставили его в покое, этот тип был бы пустым объектом. Вместо этого мне нужен какой-то способ преобразования массива строк в объединение строк. Как только я это сделаю, я могу просто ввести начальное состояние редуктора в:
{} as Record<UnionOfStrings, true>;
Тем не менее, я не могу понять, как сделать это преобразование.
Кто-нибудь знает, как это сделать?
Комментарии:
1.
const arr = ["foo", "bar"] as const; type Union = typeof arr[number];
Ответ №1:
Вам действительно не нужно использовать .reduce
для этого, так как на самом деле это не намного проще, чем просто использовать обычный старый for
цикл. Вот реализация, которую я написал с использованием for
цикла, но, вероятно, ее .reduce
также можно написать с помощью, если вы хотите.
function toObject<T extends readonly string[]>(...keys: T): Record<T[number], true> {
const obj: Record<string, true> = {};
for (const key of keys) {
obj[key] = true;
}
return obj;
}
Обратите внимание на тип возврата: Record<T[number], true>
. Я думаю, это то, что вы искали.
Комментарии:
1. аааа; рад пойти с любой петлевой структурой, но это
Record<T[number], true>
драгоценный камень.