diff --git a/source/index.ts b/source/index.ts
index 561cfcf..cda6ac3 100644
--- a/source/index.ts
+++ b/source/index.ts
@@ -2,7 +2,7 @@
///
///
-import {Class, TypedArray, ObservableLike, Primitive} from './types';
+import {Class, TypedArray, ObservableLike, Primitive, Integer} from './types';
const typedArrayTypeNames = [
'Int8Array',
@@ -258,8 +258,8 @@ is.nan = (value: unknown) => Number.isNaN(value as number);
is.primitive = (value: unknown): value is Primitive => is.null_(value) || isPrimitiveTypeName(typeof value);
-is.integer = (value: unknown): value is number => Number.isInteger(value as number);
-is.safeInteger = (value: unknown): value is number => Number.isSafeInteger(value as number);
+is.integer = (value: T): value is Integer => Number.isInteger(value);
+is.safeInteger = (value: T): value is Integer => Number.isSafeInteger(value);
is.plainObject = (value: unknown): value is Record => {
// From: https://github.com/sindresorhus/is-plain-obj/blob/main/index.js
@@ -279,7 +279,7 @@ export interface ArrayLike {
readonly length: number;
}
-const isValidLength = (value: unknown): value is number => is.safeInteger(value) && value >= 0;
+const isValidLength = (value: T): value is Integer => is.safeInteger(value) && value >= 0;
is.arrayLike = (value: unknown): value is ArrayLike => !is.nullOrUndefined(value) && !is.function_(value) && isValidLength((value as ArrayLike).length);
is.inRange = (value: number, range: number | number[]): value is number => {
@@ -336,7 +336,7 @@ is.nodeStream = (value: unknown): value is NodeStream => is.object(value) && is.
is.infinite = (value: unknown): value is number => value === Infinity || value === -Infinity;
-const isAbsoluteMod2 = (remainder: number) => (value: number): value is number => is.integer(value) && Math.abs(value % 2) === remainder;
+const isAbsoluteMod2 = (remainder: number) => (value: T): value is Integer => is.integer(value) && Math.abs(value % 2) === remainder;
is.evenInteger = isAbsoluteMod2(0);
is.oddInteger = isAbsoluteMod2(1);
@@ -509,8 +509,8 @@ interface Assert {
falsy: (value: unknown) => asserts value is unknown;
nan: (value: unknown) => asserts value is unknown;
primitive: (value: unknown) => asserts value is Primitive;
- integer: (value: unknown) => asserts value is number;
- safeInteger: (value: unknown) => asserts value is number;
+ integer: (value: T) => asserts value is Integer;
+ safeInteger: (value: T) => asserts value is Integer;
plainObject: (value: unknown) => asserts value is Record;
typedArray: (value: unknown) => asserts value is TypedArray;
arrayLike: (value: unknown) => asserts value is ArrayLike;
@@ -534,8 +534,8 @@ interface Assert {
urlSearchParams: (value: unknown) => asserts value is URLSearchParams;
// Numbers.
- evenInteger: (value: number) => asserts value is number;
- oddInteger: (value: number) => asserts value is number;
+ evenInteger: (value: T) => asserts value is Integer;
+ oddInteger: (value: T) => asserts value is Integer;
// Two arguments.
directInstanceOf: (instance: unknown, class_: Class) => asserts instance is T;
@@ -610,8 +610,8 @@ export const assert: Assert = {
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),
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),
+ integer: (value: T): asserts value is Integer => assertType(is.integer(value), AssertionTypeDescription.integer, value),
+ safeInteger: (value: T): asserts value is Integer => assertType(is.safeInteger(value), AssertionTypeDescription.safeInteger, value),
plainObject: (value: unknown): asserts value is Record => assertType(is.plainObject(value), AssertionTypeDescription.plainObject, value),
typedArray: (value: unknown): asserts value is TypedArray => assertType(is.typedArray(value), AssertionTypeDescription.typedArray, value),
arrayLike: (value: unknown): asserts value is ArrayLike => assertType(is.arrayLike(value), AssertionTypeDescription.arrayLike, value),
@@ -635,8 +635,8 @@ export const assert: Assert = {
urlSearchParams: (value: unknown): asserts value is URLSearchParams => assertType(is.urlSearchParams(value), 'URLSearchParams', value),
// Numbers.
- evenInteger: (value: number): asserts value is number => assertType(is.evenInteger(value), AssertionTypeDescription.evenInteger, value),
- oddInteger: (value: number): asserts value is number => assertType(is.oddInteger(value), AssertionTypeDescription.oddInteger, value),
+ evenInteger: (value: T): asserts value is Integer => assertType(is.evenInteger(value), AssertionTypeDescription.evenInteger, value),
+ oddInteger: (value: T): asserts value is Integer => assertType(is.oddInteger(value), AssertionTypeDescription.oddInteger, value),
// Two arguments.
directInstanceOf: (instance: unknown, class_: Class): asserts instance is T => assertType(is.directInstanceOf(instance, class_), AssertionTypeDescription.directInstanceOf, instance),
diff --git a/source/types.ts b/source/types.ts
index 8bdd0f5..2b361b0 100644
--- a/source/types.ts
+++ b/source/types.ts
@@ -47,3 +47,24 @@ export interface ObservableLike {
subscribe(observer: (value: unknown) => void): void;
[Symbol.observable](): ObservableLike;
}
+
+/**
+A `number` that is an integer.
+You can't pass a `bigint` as they are already guaranteed to be integers.
+
+Use-case: Validating and documenting parameters.
+
+@example
+```
+import {Integer} from 'type-fest';
+declare function setYear(length: Integer): void;
+```
+
+@see NegativeInteger
+@see NonNegativeInteger
+
+@category Numeric
+*/
+// `${bigint}` is a type that matches a valid bigint literal without the `n` (ex. 1, 0b1, 0o1, 0x1)
+// Because T is a number and not a string we can effectively use this to filter out any numbers containing decimal points
+export type Integer = `${Type}` extends `${bigint}` ? Type : never;