You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ES6、TypeScript和索引签名实现数据透视列转换

订单数据透视转换方案(TypeScript)

问题描述

现有如下订单数据结构:

const dataReceived: IOrder[] = [
    {customerName: 'Customer 1', customerId: '1',auctionName: 'Auction 1', auctionId: '1', statusName: 'Awaiting', statusId: '1', deliveryDate: '1', orderId: '31323'}, 
    {customerName: 'Customer 1', customerId: '1',auctionName: 'Auction 2', auctionId: '1', statusName: 'Ready',  statusId: '2',deliveryDate: '1', orderId: '42423'},
    {customerName: 'Customer 1', customerId: '1',auctionName: 'Auction 3', auctionId: '1', statusName: 'Ready', statusId: '2', deliveryDate: '1', orderId: '63353'}, 
    {customerName: 'Customer 2', customerId: '2',auctionName: 'Auction 1', auctionId: '2', statusName: 'Ready', statusId: '2', deliveryDate: '1', orderId: '23232'},
    {customerName: 'Customer 2', customerId: '2',auctionName: 'Auction 2', auctionId: '2', statusName: 'Awaiting', statusId: '1', deliveryDate: '1', orderId: '14433'},
    {customerName: 'Customer 2', customerId: '2',auctionName: 'Auction 3', auctionId: '2', statusName: 'Ready', statusId: '2', deliveryDate: '1', orderId: '25434'},
    {customerName: 'Customer 3', customerId: '3',auctionName: 'Auction 1', auctionId: '3', statusName: 'Ready', statusId: '2', deliveryDate: '1', orderId: '29332'},
    {customerName: 'Customer 3', customerId: '3',auctionName: 'Auction 2', auctionId: '3', statusName: 'Awaiting', statusId: '1', deliveryDate: '1', orderId: '37364'},
    {customerName: 'Customer 3', customerId: '3',auctionName: 'Auction 3', auctionId: '3', statusName: 'Awaiting', statusId: '1', deliveryDate: '1', orderId: '37112'},
];

对应的类型定义:

export declare type IOrder = {
    orderId: string;
    deliveryDate: string;
    customerId: string;
    customerName: string;
    auctionId: string;
    auctionName: string;
    statusId: string;
    statusName: string;
    [key: string]: string;
}

需要将数据转换为按客户聚合、以拍卖名称为动态列的结构,每个动态列对应完整的订单记录:

const dataTransformed = [
    {customerName: 'Customer 1', 
    'Auction 1': { auctionName: 'Auction 1', customerName: 'Customer 1', statusName: 'Awaiting', orderId: '31323', ...}, 
    'Auction 2': { auctionName: 'Auction 2', customerName: 'Customer 1', statusName: 'Ready', orderId: '42423', ...}, 
    'Auction 3': { auctionName: 'Auction 3', customerName: 'Customer 1', statusName: 'Ready', orderId: '63353', ...}, 
    ...}, 
    {customerName: 'Customer 2', 
    'Auction 1': { auctionName: 'Auction 1', customerName: 'Customer 2', statusName: 'Ready', orderId: '23232', ...}, 
    'Auction 2': { auctionName: 'Auction 2', customerName: 'Customer 2', statusName: 'Awaiting', orderId: '14433', ...}, 
    'Auction 3': { auctionName: 'Auction 3', customerName: 'Customer 2', statusName: 'Ready', orderId: '25434', ...}, 
    ...},
    {customerName: 'Customer 3', 
    'Auction 1': { auctionName: 'Auction 1', customerName: 'Customer 3', statusName: 'Ready', orderId: '29332', ...}, 
    'Auction 2': { auctionName: 'Auction 2', customerName: 'Customer 3', statusName: 'Awaiting', orderId: '37364', ...}, 
    'Auction 3': { auctionName: 'Auction 3', customerName: 'Customer 3', statusName: 'Awaiting', orderId: '37112', ...}, 
    ...},
];

核心痛点:拍卖名称无法预先确定,使用TypeScript索引签名时频繁报错,需要可行的类型定义和转换方案。

解决方案

1. 定义动态类型

使用TypeScript的交叉类型结合字符串索引签名,既保留固定字段(如customerName),又支持动态的拍卖名称列:

// 定义转换后的单条数据类型
type CustomerAuctionRecord = {
    customerName: string;
    customerId: string; // 可选:如果不需要可移除
} & {
    [auctionName: string]: IOrder;
};

// 最终转换后的数组类型
type TransformedData = CustomerAuctionRecord[];

2. 实现转换函数

通过Array.reduce按客户聚合数据,动态添加拍卖名称作为键:

function transformOrderData(orders: IOrder[]): TransformedData {
    return orders.reduce((acc, order) => {
        // 查找当前客户是否已存在于结果数组中
        const existingCustomer = acc.find(item => item.customerId === order.customerId);
        
        if (existingCustomer) {
            // 直接添加当前拍卖对应的订单记录
            existingCustomer[order.auctionName] = order;
        } else {
            // 创建新的客户记录,包含当前拍卖订单
            const newCustomer: CustomerAuctionRecord = {
                customerName: order.customerName,
                customerId: order.customerId,
                [order.auctionName]: order
            } as CustomerAuctionRecord; // 类型断言处理动态键的TS检查
            
            acc.push(newCustomer);
        }
        
        return acc;
    }, [] as TransformedData);
}

3. 使用示例

const dataTransformed = transformOrderData(dataReceived);

// 访问示例:获取Customer 1的Auction 1订单状态
console.log(dataTransformed[0]['Auction 1'].statusName); // 输出:Awaiting

关键说明

  • 类型断言as CustomerAuctionRecord用于绕开TypeScript对动态键的严格检查,因为拍卖名称是运行时确定的,无法提前静态推断。
  • 转换后的结构完全符合表格展示需求,每个客户一行,每个拍卖作为一列,列值为完整订单信息。

内容的提问来源于stack exchange,提问作者Rob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 01:45:35