从对象数组中移除类型安全项-是否可以在单个函数中不使用断言?

时间:2019-04-12 13:34:26

标签: typescript type-safety

我之所以问这个主要是因为我很好奇。标题可能有点复杂,所以...假设我有一个像这样的对象:

type ObjType = { items: Array<{ id: number }>; sth: number };
const obj: ObjType = {
  sth: 3,
  items: [{ id: 1 }, { id: 2 }, { id: 3 }]
};

现在,我想通过ID从obj.items中删除一项,比方说2,然后返回删除了该项目的整个对象(新对象,未突变)。在JavaScript中,这通常很简单,但是我想使用TypeScript中保留的类型安全性来做到这一点。我想到了这样的东西:

function removeItemFromArray<S, A extends { id: number }>(
  obj: S,
  field: keyof S,
  array: A[],
  valueToCompare: number
): S {
  return {
    ...obj,
    [field]: array.filter(i => i.id !== valueToCompare)
  };
}

,但是array参数似乎是多余的-它将始终为obj[field]。但是,如果我只是使用obj[field],则不能保证它是一个数组。现在的问题是如何确保obj[field]是包含id属性的对象数组?我很确定条件类型是可能的,但我不太清楚。

1 个答案:

答案 0 :(得分:1)

条件类型在这里无济于事,但是您可以通过确保obj具有正确的形状来获得所需的内容:

function removeItemFromArray<S extends { [f in F]: { id: number }[] }, F extends keyof S>(
  obj: S,
  field: F,
  valueToCompare: number
): S {
  return {
    ...obj,
    [field]: obj[field].filter(i => i.id !== valueToCompare)
  };
}

const obj = {
  sth: 3,
  items: [{ id: 1 }, { id: 2 }, { id: 3 }]
};

removeItemFromArray(obj, "items", 2);