Skip to content

Commit

Permalink
feat(types): add PickAny type, symmetric with PickOne
Browse files Browse the repository at this point in the history
  • Loading branch information
uladkasach committed May 25, 2024
1 parent b18f4e6 commit 71cb283
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export * from './companions/pick';
export * from './types/Literalize';
export * from './wrappers/withAssure';
export * from './checks/isKeyOf';
export * from './types/PickAny';
48 changes: 48 additions & 0 deletions src/types/PickAny.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { PickAny } from './PickAny';

describe('PickAny', () => {
it('should constrain type correctly', async () => {
const findFlowers = async (
input: PickAny<{
color: {
petals: string;
};
size: {
choice: 'LARGE' | 'SMALL';
};
}>,
) => {
// ...
};

// you can find by color
await findFlowers({
color: {
petals: 'white',
},
});

// you can find by size
await findFlowers({
size: {
choice: 'LARGE',
},
});

// you can find by both
await findFlowers({
color: {
petals: 'white',
},
size: {
choice: 'LARGE',
},
});

// you can't find by neither
await findFlowers({
// @ts-expect-error - cant be neither
size: {},
});
});
});
14 changes: 14 additions & 0 deletions src/types/PickAny.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* creates a type which requires specifying at least one, or more, key of an object
*
* ref:
* - https://stackoverflow.com/a/49725198/3068233
*/
export type PickAny<TObj, TKeys extends keyof TObj = keyof TObj> = Pick<
TObj,
Exclude<keyof TObj, TKeys>
> &
{
[K in TKeys]-?: Required<Pick<TObj, K>> &
Partial<Pick<TObj, Exclude<TKeys, K>>>;
}[TKeys];
19 changes: 13 additions & 6 deletions src/types/PickOne.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,18 @@ describe('PickOne', () => {
});

// you can't find by both
// await findWrench({
// size: {
// metric: { millimeters: 16 },
// imperial: { inches: '5/16' },
// },
// });
await findWrench({
// @ts-expect-error - cant be both
size: {
metric: { millimeters: 16 },
imperial: { inches: '5/16' },
},
});

// you can't find by neither
await findWrench({
// @ts-expect-error - cant be neither
size: {},
});
});
});

0 comments on commit 71cb283

Please sign in to comment.