Skip to content

Commit 527cfc3

Browse files
committed
feat(object-utilities): add getValueAssertDefined function
1 parent 8880673 commit 527cfc3

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

packages/utilities/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from './lib/group-by/group-by.js'
77
export * from './lib/http/http-constants.js'
88
export * from './lib/json-stringify-replacer/json-stringify-replacer.function.js'
99
export * from './lib/map-values-deep/map-values-deep.js'
10+
export * from './lib/object/get-value-assert-defined.function.js'
1011
export * from './lib/object/omit-props.function.js'
1112
export * from './lib/object/pick-props.function.js'
1213
export * from './lib/object/pick-props-assert-defined.function.js'
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { getValueAssertDefined } from './get-value-assert-defined.function.js'
2+
3+
describe('getValueAssertDefined', () => {
4+
interface Test {
5+
x: string | null
6+
y?: boolean
7+
z: number | undefined
8+
}
9+
10+
describe('throws when not defined', () => {
11+
const empty: Test = { x: null, z: undefined }
12+
13+
test('when null', () => {
14+
expect(() => getValueAssertDefined(empty, 'x')).toThrow()
15+
})
16+
17+
test('when undefined', () => {
18+
expect(() => getValueAssertDefined(empty, 'z')).toThrow()
19+
})
20+
21+
test('when optional', () => {
22+
expect(() => getValueAssertDefined(empty, 'y')).toThrow()
23+
})
24+
})
25+
26+
describe('returns value when defined', () => {
27+
const obj: Test = {
28+
x: '',
29+
y: false,
30+
z: 0,
31+
}
32+
33+
test('when empty string', () => {
34+
expect(getValueAssertDefined(obj, 'x')).toEqual('')
35+
})
36+
test('when false', () => {
37+
expect(getValueAssertDefined(obj, 'y')).toEqual(false)
38+
})
39+
test('when zero', () => {
40+
expect(getValueAssertDefined(obj, 'z')).toEqual(0)
41+
})
42+
43+
test('makes it type safe', () => {
44+
const tDefined: { num: number | null } = { num: 42 }
45+
// assign to variable to ensure type safety
46+
const res: number = getValueAssertDefined(tDefined, 'num')
47+
expect(res).toEqual(42)
48+
})
49+
})
50+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { isDefined } from '../ts-guards/is-defined.js'
2+
3+
/**
4+
* returns the value of the provided key on given object. throws if the value is null or undefined
5+
*/
6+
export function getValueAssertDefined<T, K extends keyof T>(obj: T, key: K): NonNullable<T[K]> {
7+
type X = NonNullable<T[K]>
8+
const value: X | null | undefined = <any>obj[key]
9+
10+
if (!isDefined(value)) {
11+
throw new Error(`Expected property "${String(key)}" to be defined. Was "${value}" instead`)
12+
}
13+
return value
14+
}

0 commit comments

Comments
 (0)