假设我有一个对象:

elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
};

我想用它的属性子集创建一个新对象。

 // pseudo code
 subset = elmo.slice('color', 'height')

 //=> { color: 'red', height: 'unknown' }

我怎样才能做到呢?


当前回答

值得注意的是,Zod模式在默认情况下会删除未知属性。如果您已经在使用Zod,那么它很可能适合您的开发过程。

https://github.com/colinhacks/zod

import { z } from "zod";

// muppet schema
const muppet = z.object({
  color: z.string(),
  annoying: z.boolean(),
  height: z.string(),
  meta: z.object({ one: z.string(), two: z.string() }),
});

// TypeScript type if you want it
type TMuppet = z.infer<typeof muppet>;

// elmo example
const elmo: TMuppet = {
  color: "red",
  annoying: true,
  height: "unknown",
  meta: { one: "1", two: "2" },
};

// get a subset of the schema (another schema) if you want
const subset = muppet.pick({ color: true, height: true });

// parsing removes unknown properties by default
subset.parse(elmo); // { color: 'red', height: 'unknown' }

其他回答

就像这个线程上的几个人一样,我同意evert的观点,最明显的老派方法实际上是最好的,但是为了好玩,让我提供另一种不可取的方法来做它在某些情况下,比如当你已经定义了你的子集,你想从另一个对象复制属性到它,其中包含一个超集或交叉集的属性。

设set = {a: 1, b: 2, c: 3}; 让子集= {a: null, b: null}; 尝试{ Object.assign (Object.seal(子集),集); } catch (e) { console.log('我想这样做<(^.^)^'); } console.log(子集);

值得注意的是,Zod模式在默认情况下会删除未知属性。如果您已经在使用Zod,那么它很可能适合您的开发过程。

https://github.com/colinhacks/zod

import { z } from "zod";

// muppet schema
const muppet = z.object({
  color: z.string(),
  annoying: z.boolean(),
  height: z.string(),
  meta: z.object({ one: z.string(), two: z.string() }),
});

// TypeScript type if you want it
type TMuppet = z.infer<typeof muppet>;

// elmo example
const elmo: TMuppet = {
  color: "red",
  annoying: true,
  height: "unknown",
  meta: { one: "1", two: "2" },
};

// get a subset of the schema (another schema) if you want
const subset = muppet.pick({ color: true, height: true });

// parsing removes unknown properties by default
subset.parse(elmo); // { color: 'red', height: 'unknown' }

动态属性的解构赋值

这个解决方案不仅适用于你的具体例子,而且更普遍适用:

const subset2 = (x, y) = > ({[x]: [y]: b}) = > ({[x]: [y]: b}); const subset3 = (x, y, z) = > ({[x]: [y]: b [z]: c}) = > ({[x]: [y]: b [z]: c}); // const subset4… Const o = {a:1, b:2, c:3, d:4, e:5}; const pickBD = subset2("b", "d"); const pickACE = subset3("a", "c", "e"); console.log ( pickBD(o), // {b:2, d:4} pickACE(o) // {a:1, c:3, e:5} );

您可以轻松地定义subset4等,以考虑更多的属性。

你可以使用逗号操作符

const elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
};

const subset = ({color , height} = elmo , {color , height});
// {color: 'red', height: 'unknown'}

在这个问题中,解构为动态命名的变量在JavaScript中是不可能的。

要动态设置键,可以使用reduce函数而不改变对象,如下所示:

const get子集= (obj,…keys) =>个key。Reduce ((a, c) =>({…A, [c]: obj[c]}), {}); Const elmo = { 颜色:红色, 讨厌:没错, 高度:“未知”, Meta: {1: '1', 2: '2'} } const子集= get子集(elmo, 'color', '烦人') console.log(子集)

应该注意的是,你是在每次迭代中创建一个新对象,而不是更新一个克隆。——mpen

下面是一个使用reduce和单个克隆的版本(更新传入的初始值以reduce)。

const get子集= (obj,…keys) =>个key。Reduce ((acc, curr) => { Acc [curr] = obj[curr] 返回acc }, {}) Const elmo = { 颜色:红色, 讨厌:没错, 高度:“未知”, Meta: {1: '1', 2: '2'} } const子集= get子集(elmo, '烦人','height', 'meta') console.log(子集)