#typescript #typescript-generics
#typescript #typescript-дженерики
Вопрос:
У меня много объектов с известными типами, и мне нужно преобразовать эти объекты в другие объекты с известными типами, подобными этому:
interface FruitesWithNoCase = {
brokenbanana: string;
brokenorange: string;
apple: number;
}
interface FruitesWithCorrectCase = {
brokenBanana: string;
brokenOrange: string;
}
const inputObject: FruitesWithNoCase = { // My input data
brokenbanana: 'foo',
brokenorange: 'bar',
apple: 123
}
const outputObject: FruitesWithCorrectCase = { // Desired result
brokenBanana: 'foo',
brokenOrange: 'bar'
}
Я не хочу сопоставлять каждый объект вручную, и было бы здорово иметь какую-то функцию, которая может принимать входной объект типа X и массив свойств, а также возвращать и выводить объект типа Y, что-то вроде:
const outputObject = getAttributes<FruitesWithNoCase, FruitesWithCorrectCase, (keyof FruitesWithCorrectCase)[]>(inputObject, ['brokenBanana', 'brokenOrange']);
- У меня всегда есть типы ввода и вывода
- У меня всегда есть список свойств, которые мне нужно выбрать в camelCase
- Я всегда уверен, что
output[prop.toLowerCase()]
существует вinput
Без типов рабочий код выглядит следующим образом:
const inputObject = {
"brokenbanana": 'foo',
"brokenorange": 'bar',
"apple": 123
}
const anotherInputObject = {
"randomcar": "Fiat",
"randomtruck": "Ford"
}
function getAttributes(obj, keys) {
return keys.reduce((acc, key) => {
acc[key] = obj[key.toLowerCase()]
return acc;
}, {});
}
const outputObject = getAttributes(inputObject, ['brokenBanana', 'brokenOrange']);
const anotherOutputObject = getAttributes(anotherInputObject, ['randomCar'])
console.log(outputObject); // { brokenBanana: 'foo', brokenOrange: 'bar' }
console.log(anotherOutputObject); // { randomCar: 'Fiat' }
Пожалуйста, помогите сделать эту функцию безопасной для ввода. Спасибо.
Ответ №1:
Сработает ли что-то подобное?
function getAttributes<T extends string>(obj: Record<string, string> , keys: T[]): Record<T, string> {
return keys.reduce((acc, key) => {
acc[key] = obj[key.toLowerCase()]
return acc;
}, {} as Record<T, string>);
}
Ответ №2:
На самом деле вы не можете вводить ключи объекта в нижний регистр и ожидать, что он когда-либо будет типобезопасным. Если вы хотите полностью сохранить тип, приведенное ниже, вероятно, лучшее, что вы получите.
const inputObject = { // My input data
brokenbanana: 'foo',
brokenorange: 'bar',
apple: 123
}
const outputObject = move(inputObject, ["brokenbanana", "brokenBanana"], ["brokenorange", "brokenOrange"])
function move<T, Old extends keyof T, New extends keyof any>(obj: T, ...map: Array<[Old, New]>): Record<New, T[Old]> {
const copy = {} as Record<New, T[Old]>;
map.forEach(([o, n]) => copy[n] = obj[o])
return copy
}