这个拍平对象的函数 ts 类型怎么写呢?

const arr = [
  {
    a: 1,
    b: [
      {
        k: 'k1',
        v: 2,
      },
      {
        k: 'k2',
        v: 2,
      },
    ],
  },
  {
    a: 1,
    b: [
      {
        k: 'k1',
        v: 2,
      },
      {
        k: 'k2',
        v: 2,
      },
    ],
  },
]

function flatData(res) {
  res.map((item) => {
    item.b.forEach((custom) => {
      item[custom.k] = custom.v
    })
    return item
  })
  return res
}

const data = flatData(arr)

console.log(data);
// [
//   { a: 1, b: [ [Object], [Object] ], k1: 2, k2: 2 },
//   { a: 1, b: [ [Object], [Object] ], k1: 2, k2: 2 }
// ]

// 推断新增的属性
data.k1
阅读 2.1k
3 个回答
interface IB {
  k: string;
  v: number;
}
interface IObj {
  a: number;
  b: IB[];
  [prop: string]: any;
}

function flatData(res: IObj[]) {
  res.map((item: IObj) => {
    item.b.forEach((custom: IB) => {
      item[custom.k] = custom.v;
    });
    return item;
  });
  return res;
}

补充:
本来要这样实现

interface IB<T>{
  k: T;
  v: number;
};

type IObj<T> = {
  a: number;
  b: IB<T>[];
  [prop : T]: number;
}

function flatData<T extends Exclude<string, 'a' | 'b'>>(res: IObj<T>[]) {
  res.map((item: IObj<T>) => {
    item.b.forEach((custom: IB<T>) => {
      item[custom.k] = custom.v; // 这样会报错
    });
    return item;
  });
  return res;
}

发现实现不了,因为你传的数据中,只有a,b属性,这样ts就会立马推断,你的对象中只有a,b属性,无法给你再增加一个k属性。
ts都是提前定义的,或者根据你的数据推断,但是只会定义一次,后续就不会再更改,因此当你改变数据的时候,ts不会再改的你的类型

所以你这个肯定是无法实现的

interface ObjItem {
  a: number,
  b: {
    k: string,
    v: number,
  }[],
  [key: string]: any
}

const obj: ObjItem[] = [
  {
    a: 1,
    b: [
      {
        k: '1111',
        v: 2,
      },
      {
        k: '222',
        v: 2,
      },
    ],
  }
];

function flatData(res: ObjItem[]) {
  res.map((item) => {
    item.b.forEach((custom) => {
      item[custom.k] = custom.v
    })
    return item
  })
  return res
}

有必要的话,复杂对象拆分一下类型比较好

vscode有个json to ts插件,你可以用这个插件来快速帮你生成ts接口类型

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进