Skip to content

Commit

Permalink
feat: add object.pick and object.omit
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Nov 19, 2020
1 parent fbc158d commit 425705a
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 10 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,36 @@ object({
});
```

#### `object.pick(keys: string[]): Schema`

Create a new schema from a subset of the original's fields.

```js
const person = object({
age: number().default(30).required(),
name: string().default('pat').required(),
color: string().default('red').required(),
});

const nameAndAge = person.pick(['name', 'age']);
nameAndAge.default(); // => { age: 30, name: 'pat'}
```

#### `object.omit(keys: string[]): Schema`

Create a new schema with fields omitted.

```js
const person = object({
age: number().default(30).required(),
name: string().default('pat').required(),
color: string().default('red').required(),
});

const nameAndAge = person.omit('color']);
nameAndAge.default(); // => { age: 30, name: 'pat'}
```

#### `object.from(fromKey: string, toKey: string, alias: boolean = false): Schema`

Transforms the specified key to a new key. If `alias` is `true` then the old key will be left.
Expand Down
23 changes: 23 additions & 0 deletions src/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,29 @@ inherits(ObjectSchema, MixedSchema, {
return next;
},

pick(keys) {
const picked = {};
for (const key of keys) {
if (this.fields[key]) picked[key] = this.fields[key];
}

return this.clone().withMutation((next) => {
next.fields = {};
return next.shape(picked);
});
},

omit(keys) {
const next = this.clone();
const fields = next.fields;
next.fields = {};
for (const key of keys) {
delete fields[key];
}

return next.withMutation((next) => next.shape(fields));
},

from(from, to, alias) {
let fromGetter = getter(from, true);

Expand Down
47 changes: 37 additions & 10 deletions test/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ describe('Object types', () => {
let inst = lazy((_, options) => {
options.should.equal(opts);
done();
return string();
return object();
});

inst.cast({ nested: 'foo' }, opts);
Expand Down Expand Up @@ -863,15 +863,6 @@ describe('Object types', () => {
expect(inst.nullable().cast(null)).to.equal(null);
});

// it('should camelCase with leading underscore', () => {
// let inst = object().camelCase()
//
// inst
// .cast({ CON_STAT: 5, __isNew: true, __IS_FUN: true })
// .should
// .eql({ conStat: 5, __isNew: true, __isFun: true })
// })

it('should CONSTANT_CASE keys', () => {
let inst = object()
.shape({
Expand All @@ -888,6 +879,42 @@ describe('Object types', () => {
expect(inst.nullable().cast(null)).to.equal(null);
});

it('should pick', async () => {
let inst = object({
age: number().default(30).required(),
name: string().default('pat').required(),
color: string().default('red').required(),
});

expect(inst.pick(['age', 'name']).default()).to.eql({
age: 30,
name: 'pat',
});

expect(
await inst.pick(['age', 'name']).validate({ age: 24, name: 'Bill' }),
).to.eql({
age: 24,
name: 'Bill',
});
});

it('should omit', async () => {
let inst = object({
age: number().default(30).required(),
name: string().default('pat').required(),
color: string().default('red').required(),
});

expect(inst.omit(['age', 'name']).default()).to.eql({
color: 'red',
});

expect(
await inst.omit(['age', 'name']).validate({ color: 'mauve' }),
).to.eql({ color: 'mauve' });
});

xit('should handle invalid shapes better', async () => {
var schema = object().shape({
permissions: undefined,
Expand Down

0 comments on commit 425705a

Please sign in to comment.