#arrays #typescript #subset
#массивы #typescript #подмножество
Вопрос:
Допустим, у меня есть функция, подобная следующей:
function getUserInfo(desiredProperties: ('name' | 'age' | 'salary')[]) {
const userInfo: Record<string, unknown> = {};
for (const propertyName of desiredProperties) {
userInfo[propertyName] = fetchEffortfullyFromDatabase(...);
}
return userInfo;
}
Теперь, если я вызову функцию «нормально», скажем
const userInfo = getUserInfo(['name', 'salary']);
все в порядке.
Но ничто не мешает вызвать такой
const userInfo = getUserInfo(['name', 'name', 'name', ...]);
запуск множества ненужных обращений к базе данных. Конечно, это можно просто обработать во getUserInfo
время выполнения, но я хочу, чтобы компилятор распознавал и запрещал такие вызовы.
Я мог бы перейти ('name' | 'age' | 'salary')[]
на объединение всех возможных комбинаций имен свойств, т. Е. ['name'] | ['name', 'age'] | ['name', 'age', 'salary'] | ['age'] | ...
, Но это слишком утомительно даже для трех значений и вряд ли выполнимо для большего количества (особенно с учетом порядка).
Итак, есть ли другой способ получить желаемый ввод? Может быть, что-то вроде AllCombinations<'name', 'age', 'salary'>
?
Ответ №1:
Вы можете использовать Set
возможность ввода для извлечения только уникальных членов переданного аргумента:
function getUserInfo(desiredProperties: ('name' | 'age' | 'salary')[]) {
const uniqueMembers = new Set(desiredProperties); // this extract only unique members of array
const userInfo: Record<string, unknown> = {};
for (const propertyName of uniqueMembers) { // and here you iterate only through unique members
userInfo[propertyName] = fetchEffortfullyFromDatabase(...);
}
return userInfo;
}
let userInfo = getUserInfo(['name', 'salary']);
userInfo = getUserInfo(['name', 'name', 'name']);
Конечно, такое решение не идеально, поскольку оно предполагает ненужные вычисления во время выполнения.
Если вы не хотите выполнять ненужные вычисления, вы можете установить тип desiredProperties
as Set<'name' | 'age' | 'salary'>
. А затем вызовите getUserInfo
вот так:
const userInfo = getUserInfo(new Set(['name', 'salary']));