Skip to content

Commit 6d91178

Browse files
committed
Include require props helpers
1 parent e2e2491 commit 6d91178

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@makerx/node-common",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"private": false,
55
"description": "A set of MakerX core NodeJS types and utilities",
66
"author": "MakerX",

src/type-helpers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './require-props'

src/type-helpers/require-props.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Invariant assertion that the given object has the specified properties, and that they are not null or undefined.
3+
*
4+
* @param obj The object to check
5+
* @param props The properties to check
6+
*
7+
* Usage:
8+
* ```
9+
* const obj: { maybeProp?: string } = { maybeProp: 'hello' }
10+
*
11+
* // Optional chaining required
12+
* console.log(obj.maybeProp?.toLowerCase())
13+
*
14+
* requireProps(obj, 'maybeProp')
15+
*
16+
* // Optional chaining not required as we have asserted it is not null or undefined
17+
* console.log(obj.maybeProp.toLowerCase())
18+
* ```
19+
*/
20+
export function requireProps<T, TProps extends keyof T & string>(obj: T, ...props: TProps[]): asserts obj is RequireSomeProps<T, TProps> {
21+
for (const prop of props) {
22+
if (obj[prop] === undefined || obj[prop] === null) throw new Error(`Missing mandatory field ${prop}`)
23+
}
24+
}
25+
26+
/**
27+
* Returns a filter function that: returns true if the given object has the specified properties, and they are not null or undefined.
28+
* @param props The properties to check
29+
*
30+
* Usage:
31+
* ```
32+
* const objects: Array<{ maybeProp?: string }> = [{ maybeProp: 'hello' }, {}, {maybeProp: 'foo'}]
33+
*
34+
* // res1 type is Array<string | undefined> because there is no type assertion
35+
* const res1 = objects.filter(x => x.maybeProp != undefined).map(x => x.maybeProp)
36+
*
37+
* // res2 type is Array<string> due to type assertion that required props will not be null or undefined
38+
* const res2 = objects.filter(hasRequiredProps('maybeProp')).map(x => x.maybeProp)
39+
* ```
40+
*/
41+
export const hasRequiredProps =
42+
<T, TProps extends keyof T & string>(...props: TProps[]) =>
43+
(obj: T): obj is RequireSomeProps<T, TProps> => {
44+
requireProps(obj, ...props)
45+
return true
46+
}
47+
48+
export type RequireSomeProps<T, TProps extends keyof T> = {
49+
[key in TProps]-?: Exclude<T[key], null | undefined>
50+
} & T

0 commit comments

Comments
 (0)