Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix type guards for assert.{truthy,falsy,nan} #187

Merged
merged 3 commits into from
Jul 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions source/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ is.urlString = (value: unknown): value is string => {
is.truthy = <T>(value: T | Falsy): value is T => Boolean(value); // eslint-disable-line unicorn/prefer-native-coercion-functions

// Example: `is.falsy = (value: unknown): value is (not true | 0 | '' | undefined | null) => Boolean(value);`
is.falsy = <T>(value: T | Falsy): value is Falsy => !value;
is.falsy = (value: unknown): value is Falsy => !value;

is.nan = (value: unknown) => Number.isNaN(value as number);

Expand Down Expand Up @@ -570,9 +570,9 @@ type Assert = {
enumCase: <T = unknown>(value: unknown, targetEnum: T) => asserts value is T[keyof T];
urlInstance: (value: unknown) => asserts value is URL;
urlString: (value: unknown) => asserts value is string;
truthy: (value: unknown) => asserts value is unknown;
falsy: (value: unknown) => asserts value is unknown;
nan: (value: unknown) => asserts value is unknown;
truthy: <T>(value: T | Falsy) => asserts value is T;
falsy: (value: unknown) => asserts value is Falsy;
nan: (value: unknown) => asserts value is number;
primitive: (value: unknown) => asserts value is Primitive;
integer: (value: unknown) => asserts value is number;
safeInteger: (value: unknown) => asserts value is number;
Expand Down Expand Up @@ -678,9 +678,9 @@ export const assert: Assert = {
enumCase: <T = unknown>(value: unknown, targetEnum: T): asserts value is T[keyof T] => assertType(is.enumCase(value, targetEnum), 'EnumCase', value),
urlInstance: (value: unknown): asserts value is URL => assertType(is.urlInstance(value), 'URL', value),
urlString: (value: unknown): asserts value is string => assertType(is.urlString(value), AssertionTypeDescription.urlString, value),
truthy: (value: unknown): asserts value is unknown => assertType(is.truthy(value), AssertionTypeDescription.truthy, value),
falsy: (value: unknown): asserts value is unknown => assertType(is.falsy(value), AssertionTypeDescription.falsy, value),
nan: (value: unknown): asserts value is unknown => assertType(is.nan(value), AssertionTypeDescription.nan, value),
truthy: <T>(value: T | Falsy): asserts value is T => assertType(is.truthy(value), AssertionTypeDescription.truthy, value),
falsy: (value: unknown): asserts value is Falsy => assertType(is.falsy(value), AssertionTypeDescription.falsy, value),
nan: (value: unknown): asserts value is number => assertType(is.nan(value), AssertionTypeDescription.nan, value),
primitive: (value: unknown): asserts value is Primitive => assertType(is.primitive(value), AssertionTypeDescription.primitive, value),
integer: (value: unknown): asserts value is number => assertType(is.integer(value), AssertionTypeDescription.integer, value),
safeInteger: (value: unknown): asserts value is number => assertType(is.safeInteger(value), AssertionTypeDescription.safeInteger, value),
Expand Down
101 changes: 101 additions & 0 deletions test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,54 @@ test('is.truthy', t => {
t.notThrows(() => {
assert.truthy(BigInt(1));
});

// Checks that `assert.truthy` narrow downs boolean type to `true`.
{
const booleans = [true, false];
const function_ = (value: true) => value;
assert.truthy(booleans[0]);
function_(booleans[0]);
}

// Checks that `assert.truthy` excludes zero value from number type.
{
const bits: Array<0 | 1> = [1, 0, -0];
const function_ = (value: 1) => value;
assert.truthy(bits[0]);
function_(bits[0]);
}

// Checks that `assert.truthy` excludes zero value from bigint type.
{
const bits: Array<0n | 1n> = [1n, 0n, -0n];
const function_ = (value: 1n) => value;
assert.truthy(bits[0]);
function_(bits[0]);
}

// Checks that `assert.truthy` excludes empty string from string type.
{
const strings: Array<'nonEmpty' | ''> = ['nonEmpty', ''];
const function_ = (value: 'nonEmpty') => value;
assert.truthy(strings[0]);
function_(strings[0]);
}

// Checks that `assert.truthy` excludes undefined from mixed type.
{
const maybeUndefineds = ['🦄', undefined];
const function_ = (value: string) => value;
assert.truthy(maybeUndefineds[0]);
function_(maybeUndefineds[0]);
}

// Checks that `assert.truthy` excludes null from mixed type.
{
const maybeNulls = ['🦄', null];
const function_ = (value: string) => value;
assert.truthy(maybeNulls[0]);
function_(maybeNulls[0]);
}
});

test('is.falsy', t => {
Expand Down Expand Up @@ -1119,6 +1167,59 @@ test('is.falsy', t => {
t.notThrows(() => {
assert.falsy(BigInt(0));
});

// Checks that `assert.falsy` narrow downs boolean type to `false`.
{
const booleans = [false, true];
const function_ = (value: false) => value;
assert.falsy(booleans[0]);
function_(booleans[0]);
}

// Checks that `assert.falsy` narrow downs number type to `0`.
{
const bits = [0, -0, 1];
const function_ = (value: 0) => value;
assert.falsy(bits[0]);
function_(bits[0]);
assert.falsy(bits[1]);
function_(bits[1]);
}

// Checks that `assert.falsy` narrow downs bigint type to `0n`.
{
const bits = [0n, -0n, 1n];
const function_ = (value: 0n) => value;
assert.falsy(bits[0]);
function_(bits[0]);
assert.falsy(bits[1]);
function_(bits[1]);
}

// Checks that `assert.falsy` narrow downs string type to empty string.
{
const strings = ['', 'nonEmpty'];
const function_ = (value: '') => value;
assert.falsy(strings[0]);
function_(strings[0]);
}

// Checks that `assert.falsy` can narrow down mixed type to undefined.
{
const maybeUndefineds = [undefined, Symbol('🦄')];
const function_ = (value: undefined) => value;
assert.falsy(maybeUndefineds[0]);
function_(maybeUndefineds[0]);
}

// Checks that `assert.falsy` can narrow down mixed type to null.
{
const maybeNulls = [null, Symbol('🦄')];
// eslint-disable-next-line @typescript-eslint/ban-types
const function_ = (value: null) => value;
assert.falsy(maybeNulls[0]);
function_(maybeNulls[0]);
}
});

test('is.nan', t => {
Expand Down