diff --git a/src/index.ts b/src/index.ts index 00665eee..1529803f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,6 +43,7 @@ export { getTargetScrollBarSize, } from './getScrollBarSize'; export { default as isEqual } from './isEqual'; +export { isNonNullable, isReactRenderable } from './is'; export { default as isMobile } from './isMobile'; export { default as omit } from './omit'; export { default as pickAttrs } from './pickAttrs'; diff --git a/src/is.ts b/src/is.ts new file mode 100644 index 00000000..eae4d3d7 --- /dev/null +++ b/src/is.ts @@ -0,0 +1,21 @@ +/** + * Check if a value is neither `null` nor `undefined`. + */ +export function isNonNullable(value: T): value is NonNullable { + return value !== undefined && value !== null; +} + +/** + * Check whether a value should be treated as renderable content. + * + * Returns `false` only for `null`, `undefined`, `false`, and `''`; all other + * values, including `0` and `true`, are treated as renderable. + * + * This is a compatibility-oriented presence check, not a complete React node + * validator. + */ +export function isReactRenderable( + value: T, +): value is Exclude, false | ''> { + return isNonNullable(value) && value !== false && value !== ''; +} diff --git a/tests/is.test.tsx b/tests/is.test.tsx new file mode 100644 index 00000000..e636b9eb --- /dev/null +++ b/tests/is.test.tsx @@ -0,0 +1,32 @@ +import { isNonNullable, isReactRenderable } from '../src'; + +describe('is', () => { + describe('isNonNullable', () => { + it.each([undefined, null])('returns false for nullable value %p', value => { + expect(isNonNullable(value)).toBeFalsy(); + }); + + it.each([false, '', 0, 'text', ])( + 'returns true for non-nullable value %p', + value => { + expect(isNonNullable(value)).toBeTruthy(); + }, + ); + }); + + describe('isReactRenderable', () => { + it.each([undefined, null, false, ''])( + 'returns false for non-renderable value %p', + value => { + expect(isReactRenderable(value)).toBeFalsy(); + }, + ); + + it.each([0, true, 'text', ])( + 'returns true for renderable value %p', + value => { + expect(isReactRenderable(value)).toBeTruthy(); + }, + ); + }); +});