Skip to content

Commit

Permalink
add "Nullish" type alias (#152)
Browse files Browse the repository at this point in the history
* add "Nullish" type alias

Introduced in TS 3.7 with nullish coalescing operator (see [here][1])

[1]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing

* Update README.md

* update tests

* cleanup
  • Loading branch information
zhirzh authored Sep 11, 2020
1 parent 9df4858 commit 11e48e8
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 2 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ We are open for contributions. If you're planning to contribute please make sure
* [`isPrimitive`](#isprimitive)
* [`Falsy`](#falsy)
* [`isFalsy`](#isfalsy)
* [`Nullish`](#nullish)
* [`isNullish`](#isnullish)

## Union operators

Expand Down Expand Up @@ -205,6 +207,27 @@ const consumer = (param: Falsy | string): string => {

[⇧ back to top](#table-of-contents)

### `Nullish`

Type representing [nullish values](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing) in TypeScript: `null | undefined`

[⇧ back to top](#table-of-contents)

### `isNullish`

```ts
const consumer = (param: Nullish | string): string => {
if (isNullish(param)) {
// typeof param === Nullish
return String(param) + ' was Nullish';
}
// typeof param === string
return param.toString();
};
```

[⇧ back to top](#table-of-contents)

### `SetIntersection<A, B>` (same as Extract)

Set intersection of given union types `A` and `B`
Expand Down
4 changes: 4 additions & 0 deletions src/__snapshots__/aliases-and-guards.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ exports[`isFalsy param (type) should match snapshot 1`] = `"false | 0 | null | u
exports[`isFalsy param (type) should match snapshot 2`] = `"string"`;
exports[`isNullish param (type) should match snapshot 1`] = `"Nullish"`;
exports[`isNullish param (type) should match snapshot 2`] = `"string"`;
exports[`isPrimitive param (type) should match snapshot 1`] = `"Primitive"`;
exports[`isPrimitive param (type) should match snapshot 2`] = `"Primitive[]"`;
39 changes: 38 additions & 1 deletion src/aliases-and-guards.spec.snap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { testType } from '../utils/test-utils';
import { Primitive, isPrimitive, Falsy, isFalsy } from './aliases-and-guards';
import {
Primitive,
isPrimitive,
Falsy,
isFalsy,
Nullish,
isNullish,
} from './aliases-and-guards';

// @dts-jest:group Primitive
{
Expand Down Expand Up @@ -59,3 +66,33 @@ it('returns false for truthy', () => {
const testResults = truthyTestVals.map(isFalsy);
testResults.forEach(val => expect(val).toBe(false));
});

// @dts-jest:group isNullish
it('narrows to correct type', () => {
const consumer = (param: Nullish | string): string => {
if (isNullish(param)) {
// @dts-jest:pass:snap -> Nullish
param;
return String(param) + ' was Nullish';
}
// @dts-jest:pass:snap -> string
param;
return param.toString();
};
});

// @dts-jest:group isNullish - test nullish values
it('returns true for nullish', () => {
const nullishTestVals: unknown[] = [null, undefined];

const testResults = nullishTestVals.map(isNullish);
testResults.forEach(val => expect(val).toBe(true));
});

// @dts-jest:group isNullish - test non-nullish values
it('returns false for non-nullish', () => {
const nonNullishTestVals: unknown[] = [false, '', 0, ' ', true, {}, []];

const testResults = nonNullishTestVals.map(isNullish);
testResults.forEach(val => expect(val).toBe(false));
});
39 changes: 38 additions & 1 deletion src/aliases-and-guards.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { testType } from '../utils/test-utils';
import { Primitive, isPrimitive, Falsy, isFalsy } from './aliases-and-guards';
import {
Primitive,
isPrimitive,
Falsy,
isFalsy,
Nullish,
isNullish,
} from './aliases-and-guards';

// @dts-jest:group Primitive
{
Expand Down Expand Up @@ -59,3 +66,33 @@ it('returns false for truthy', () => {
const testResults = truthyTestVals.map(isFalsy);
testResults.forEach(val => expect(val).toBe(false));
});

// @dts-jest:group isNullish
it('narrows to correct type', () => {
const consumer = (param: Nullish | string): string => {
if (isNullish(param)) {
// @dts-jest:pass:snap
param;
return String(param) + ' was Nullish';
}
// @dts-jest:pass:snap
param;
return param.toString();
};
});

// @dts-jest:group isNullish - test nullish values
it('returns true for nullish', () => {
const nullishTestVals: unknown[] = [null, undefined];

const testResults = nullishTestVals.map(isNullish);
testResults.forEach(val => expect(val).toBe(true));
});

// @dts-jest:group isNullish - test non-nullish values
it('returns false for non-nullish', () => {
const nonNullishTestVals: unknown[] = [false, '', 0, ' ', true, {}, []];

const testResults = nonNullishTestVals.map(isNullish);
testResults.forEach(val => expect(val).toBe(false));
});
25 changes: 25 additions & 0 deletions src/aliases-and-guards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ export type Primitive =
*/
export type Falsy = false | '' | 0 | null | undefined;

/**
* Nullish
* @desc Type representing [nullish values][https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing] in TypeScript: `null | undefined`
* @example
* type Various = 'a' | 'b' | undefined;
*
* // Expect: "a" | "b"
* Exclude<Various, Nullish>;
*/
export type Nullish = null | undefined;

/**
* Tests for one of the [`Primitive`](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) types using the JavaScript [`typeof`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) operator
*
Expand Down Expand Up @@ -76,3 +87,17 @@ export const isPrimitive = (val: unknown): val is Primitive => {
* };
*/
export const isFalsy = (val: unknown): val is Falsy => !val;

/**
* Tests for Nullish by simply comparing `val` for equality with `null`.
* @example
* const consumer = (param: Nullish | string): string => {
* if (isNullish(param)) {
* // typeof param === Nullish
* return String(param) + ' was Nullish';
* }
* // typeof param === string
* return param.toString();
* };
*/
export const isNullish = (val: unknown): val is Nullish => val == null;
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export {
Falsy,
Falsy as Falsey, // deprecated in v3, backward compatibility until v4
isFalsy,
Nullish,
isNullish,
Primitive,
isPrimitive,
} from './aliases-and-guards';
Expand Down

0 comments on commit 11e48e8

Please sign in to comment.