从TypeScript对象中删除动态键

11
在TypeScript中,克隆一个对象非常简单: const a = {...b} 或者克隆并更新: const a = {...b, c: 'd'} 例如,我有这段代码:
const a = {
    'something': 1,
    'e': 2,
};
const c = 'something';
delete a[c];

有没有一种好的方法可以删除对象的属性,而不是使用传统的delete a[c]方式?(当然也不是a[c] = undefined


我认为你正在寻找 const { [c]: _, ...withootC } = a; - Aleksey L.
1
啊,太棒了。你能添加一个答案并解释一下它是如何工作的吗?这正是我在寻找的。 - Nguyen Phong Thien
3个回答

27

你正在寻找计算属性名和解构的组合。更多信息请参见此处

const a = {
    'something': 1,
    'e': 2,
};

const c = 'something';

const { [c]: _, ...withoutC } = a;

在这里,我们将c变量中的属性something的值放入_变量中,而其他所有属性都放入withoutC变量中。c定义为const的事实使得TypeScript可以正确地推断出withoutC的类型。


8
不要从 a 中删除属性,使用解构赋值创建一个不包含该属性的新对象:
const {c, ...b} = a;

在此之后,b 将包含除 c 以外的所有 a 成员。
假设 a 是某种类型,比如 { c: string, d: string },则 cb 的类型将被推断为分别是 string{ d: string }。当然,如果必须显式地编写这些类型注释,使用 Omit 类型,如 @Nurbol Alpybayev 建议的那样,通常比长形式更好。
您可以使用以下语法来重命名 c 以避免与另一个名称冲突:
const {c: someOtherName, ...b} = a;

如果您在编译时知道属性名称,则上述方法可行。如果在您的情况下不是这种情况,则TypeScript编译器无法提供太多帮助,因为它将无法确定操作的结果类型。

您最好将a键入为{ [k: string]: number },在这种情况下,delete a[c]将是可以的,或者您可以使用以下内容:

const exclude = <T>(map: { [k: string]: T }, omitted: string[]): { [k: string]: T } =>
  return Object.getOwnPropertyNames(a)
    .filter(k => omitted.indexOf(k) >= 0)
    .reduce((a, k) => (a[k] = map[k], a), {})
};
var b = exclude(a, ["c"]);

非常接近,但在我的情况下,它有点更加复杂。例如:const a = { 'something': 1, 'e': 2, }; const c = 'something'; const { 'something': undefined, ...b } = a;可以工作,但是const a = { 'something': 1, 'e': 2, }; const c = 'something'; const { c: undefined, ...b } = a;不行。 - Nguyen Phong Thien
所以这里的重点是 c 不是一个字符串 'c'。它是一个变量 const c = 'something'。希望这次已经足够清楚了。 - Nguyen Phong Thien
@NguyenPhongThien 我仍然不确定我是否理解了问题。如果您要删除的属性在编译时已知,那么我的方法将起作用。如果属性名称在编译时未知,则无法确定表达式的结果类型(除了像 { [k: string]: number } 这样的映射类型)。 - p.s.w.g
不,这完全不是问题。我正在寻找一种更好的方法来克隆一个对象并从中删除一个键,而不是使用const a = {...b}; delete a[c];,然后在稍后使用b = {...a}。因为我暂时不想改变原始对象。但如果不可能,这仍然不会是一个大问题。 - Nguyen Phong Thien
@NguyenPhongThien 我添加了一种更符合惯用法的解决方案,比 const a = {...b}; delete a[c]; 更好。 - p.s.w.g

0
当然可以!您可以使用“Omit”类型来实现此操作:Omit
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>

type DeleteBar = Omit<{bar: 123, baz: 123}, 'bar'> // {baz: 123}

顺便说一下,我意识到你可能问的是值,而不是类型。你应该询问关于JavaScript,而不是TypeScript。


1
它似乎并不起作用,您能告诉我在这种情况下它是如何工作的吗? 'something': 1, 'e': 2, }; const c = 'something'; delete a[c];``` - Nguyen Phong Thien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接