Как правильно выполнить типизацию функции трансформации данных?
Всем привет, у меня есть функция трансформации данных:
const orders = [
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Приход",
"docId": 564564867361367,
"image": "https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"name": "Молочный Изюм 100",
"price": 102,
"quantity": 45,
"removed": 0
},
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Приход",
"docId": 564564867361367,
"image": "https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"name": "Русская картошка чедар 50",
"price": 46.3,
"quantity": 45,
"removed": 0
},
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Расход",
"docId": 564564867361367,
"image": "https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"name": "Русская картошка чедар 50",
"price": 46.3,
"quantity": 45,
"removed": 0
},
{
"date": "2017-11-29 17:26:57",
"docTypesName": "Расход",
"docId": 564564867361365,
"image": "https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"name": "Молочный Изюм 100",
"price": 102,
"quantity": 6,
"removed": 0
},
]
interface IOrder {
date: string,
docTypesName: string,
docId: number,
image: string,
name: string,
price: number,
quantity: number,
removed: number,
}
interface IProduct {
image: string,
name: string,
price: number,
quantity: number,
}
interface IDocument {
date: string,
docId: number,
docTypesName: string,
products: IProduct[],
}
interface IElement {
date: string,
documents: IDocument[]
}
interface IResult {
'2017-10-16': IElement,
}
function f(orders: IOrder[]) {
const result: IElement = orders.reduce((accumulator: any, currentValue: IOrder) => {
const date = currentValue.date.split(' ')[0];
if (!accumulator[date]) {
accumulator[date] = {
date,
documents: {},
}
}
if (!accumulator[date].documents[currentValue.docTypesName]) {
accumulator[date].documents[currentValue.docTypesName] = {
date: currentValue.date,
docId: currentValue.docId,
docTypesName: currentValue.docTypesName,
products: [],
}
}
accumulator[date].documents[currentValue.docTypesName].products.push({
name: currentValue.name,
price: currentValue.price,
image: currentValue.image,
qunatity: currentValue.quantity,
})
return accumulator;
}, {})
console.log('result', result);
return Object.values(result).map((currentValue: IElement) => {
console.log('currentValue', currentValue);
if (currentValue.documents) {
currentValue.documents = Object.values(currentValue.documents);
}
return currentValue;
});
}
console.log(f(orders));
Подскажите пожалуйста, как более правильно описать типизацию и как правильно типизировать вот этот момент, соответственно избавиться от any?
const result: IElement = orders.reduce((accumulator: any, currentValue: IOrder) => {
Ответы (2 шт):
Автор решения: qwabra
→ Ссылка
Подскажите пожалуйста, как ... избавиться от any?
Да очень просто:
const result: IElement = orders.reduce((previousValue, currentValue) => null as any, {} as IElement)
Полное решение для частного случая
function f(orders: I.Order[]): I.accumulator<"B"> {
const accumulator: I.accumulator<"A"> = orders.reduce((accumulator, currentValue): I.accumulator<"A"> => {
const date = currentValue.date.split(' ')[0]
if (!accumulator[date]) {
accumulator[date] = {
date,
documents: {},
}
}
const documents = accumulator[date].documents
if (!documents[currentValue.docTypesName]) {
documents[currentValue.docTypesName] = {
date: currentValue.date,
docId: currentValue.docId,
docTypesName: currentValue.docTypesName,
products: [],
}
}
const { name, price, image, quantity } = currentValue
documents[currentValue.docTypesName]
.products.push({ name, price, image, quantity })
return accumulator
}, {} as I.accumulator<"A">)
console.log('result', accumulator)
return transform(accumulator)
}
function transform(accumulator: I.accumulator<"A">): I.accumulator<"B"> {
const result: I.accumulator<"B"> = accumulator as any
for (let key in accumulator) {
result[key].documents = Object.values(accumulator[key].documents)
}
return result
}
namespace I {
export interface Element {
date: string,
documents: Document[]
}
export interface Document {
date: Element['date'],
docId: number,
docTypesName: string,
products: Product[],
}
export interface Product {
image: string,
name: string,
price: number,
quantity: number,
}
// так не работает ;(
// export interface Order extends Product extends Omit<Document, 'products'> {
// removed: number,
// }
export type Order = Product & Omit<Document, 'products'> & {
removed: number,
}
export namespace accumulator {
export type documentsVals = any[]
export type documents = Record<Document['docTypesName'], Document>
}
export type accumulator<T extends "A" | "B"> = Record<string, {
date: string,
documents: T extends "A" ? accumulator.documents : any[]
}>
}
тут обнаружилась ошибка
documents[currentValue.docTypesName].products.push({
name: currentValue.name,
price: currentValue.price,
image: currentValue.image,
//FIXME: qunatity !== quantity
qunatity: currentValue.quantity,
})
Автор решения: Artyom Kozhemiakin
→ Ссылка
Типизированный код без единого приведения типов или any:
const orders = [
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Приход",
"docId": 564564867361367,
"image": "https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"name": "Молочный Изюм 100",
"price": 102,
"quantity": 45,
"removed": 0
},
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Приход",
"docId": 564564867361367,
"image": "https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"name": "Русская картошка чедар 50",
"price": 46.3,
"quantity": 45,
"removed": 0
},
{
"date": "2017-10-16 12:07:07",
"docTypesName": "Расход",
"docId": 564564867361367,
"image": "https://mariupolcena.com/files/products/9ff44136e6ccb0afb404ad26f727e67d.jpeg",
"name": "Русская картошка чедар 50",
"price": 46.3,
"quantity": 45,
"removed": 0
},
{
"date": "2017-11-29 17:26:57",
"docTypesName": "Расход",
"docId": 564564867361365,
"image": "https://www.komus.ru/medias/sys_master/root/hd3/h93/9286922043422.jpg",
"name": "Молочный Изюм 100",
"price": 102,
"quantity": 6,
"removed": 0
},
]
interface IOrder {
date: string,
docTypesName: string,
docId: number,
image: string,
name: string,
price: number,
quantity: number,
removed: number,
}
interface IProduct {
image: string,
name: string,
price: number,
quantity: number,
}
interface IDocument {
date: string,
docId: number,
docTypesName: string,
products: IProduct[],
}
interface IElement {
date: string,
documents: IDocument[]
}
interface AccumulatorItem {
date: string;
documents: Record<string, IDocument>
}
type Accumulator = Record<string, AccumulatorItem>
function f(orders: IOrder[]): IElement[] {
const result = orders.reduce<Accumulator>((accumulator, currentValue) => {
const date = currentValue.date.split(' ')[0];
if (!accumulator[date]) {
accumulator[date] = {
date,
documents: {},
}
}
if (!accumulator[date].documents[currentValue.docTypesName]) {
accumulator[date].documents[currentValue.docTypesName] = {
date: currentValue.date,
docId: currentValue.docId,
docTypesName: currentValue.docTypesName,
products: [],
}
}
accumulator[date].documents[currentValue.docTypesName].products.push({
name: currentValue.name,
price: currentValue.price,
image: currentValue.image,
quantity: currentValue.quantity,
})
return accumulator;
}, {})
console.log('result', result);
return Object.values(result).map((currentValue) => {
console.log('currentValue', currentValue);
return {
...currentValue,
documents: Object.values(currentValue.documents),
}
});
}
console.log(f(orders));