diff --git a/_annotation.ts b/_annotation.ts index 3d96d6f..73fa314 100644 --- a/_annotation.ts +++ b/_annotation.ts @@ -46,6 +46,11 @@ export type AsReadonly = { /** * Annotation for predObj. */ -export type WithPredObj>> = { +export type IsPredObj< + T extends Record> = Record< + PropertyKey, + Predicate + >, +> = { predObj: T; }; diff --git a/is/__snapshots__/array_of_test.ts.snap b/is/__snapshots__/array_of_test.ts.snap deleted file mode 100644 index be5103b..0000000 --- a/is/__snapshots__/array_of_test.ts.snap +++ /dev/null @@ -1,5 +0,0 @@ -export const snapshot = {}; - -snapshot[`isArrayOf > returns properly named function 1`] = `"isArrayOf(isNumber)"`; - -snapshot[`isArrayOf > returns properly named function 2`] = `"isArrayOf((anonymous))"`; diff --git a/is/__snapshots__/instance_of_test.ts.snap b/is/__snapshots__/instance_of_test.ts.snap deleted file mode 100644 index 29206ee..0000000 --- a/is/__snapshots__/instance_of_test.ts.snap +++ /dev/null @@ -1,5 +0,0 @@ -export const snapshot = {}; - -snapshot[`isInstanceOf > returns properly named function 1`] = `"isInstanceOf(Date)"`; - -snapshot[`isInstanceOf > returns properly named function 2`] = `"isInstanceOf((anonymous))"`; diff --git a/is/__snapshots__/intersection_of_test.ts.snap b/is/__snapshots__/intersection_of_test.ts.snap index 004da6e..56278e4 100644 --- a/is/__snapshots__/intersection_of_test.ts.snap +++ b/is/__snapshots__/intersection_of_test.ts.snap @@ -1,15 +1,15 @@ export const snapshot = {}; -snapshot[`isIntersectionOf > returns properly named function 1`] = ` +snapshot[`isIntersectionOf > returns properly named predicate function 1`] = `"isString"`; + +snapshot[`isIntersectionOf > returns properly named predicate function 2`] = ` "isObjectOf({ a: isNumber, b: isString })" `; -snapshot[`isIntersectionOf > returns properly named function 2`] = `"isString"`; - -snapshot[`isIntersectionOf > returns properly named function 3`] = ` +snapshot[`isIntersectionOf > returns properly named predicate function 3`] = ` "isIntersectionOf([ isFunction, isObjectOf({b: isString}) diff --git a/is/__snapshots__/literal_of_test.ts.snap b/is/__snapshots__/literal_of_test.ts.snap deleted file mode 100644 index e7e6c72..0000000 --- a/is/__snapshots__/literal_of_test.ts.snap +++ /dev/null @@ -1,15 +0,0 @@ -export const snapshot = {}; - -snapshot[`isLiteralOf > returns properly named function 1`] = `'isLiteralOf("hello")'`; - -snapshot[`isLiteralOf > returns properly named function 2`] = `"isLiteralOf(100)"`; - -snapshot[`isLiteralOf > returns properly named function 3`] = `"isLiteralOf(100n)"`; - -snapshot[`isLiteralOf > returns properly named function 4`] = `"isLiteralOf(true)"`; - -snapshot[`isLiteralOf > returns properly named function 5`] = `"isLiteralOf(null)"`; - -snapshot[`isLiteralOf > returns properly named function 6`] = `"isLiteralOf(undefined)"`; - -snapshot[`isLiteralOf > returns properly named function 7`] = `"isLiteralOf(Symbol(asdf))"`; diff --git a/is/__snapshots__/literal_one_of_test.ts.snap b/is/__snapshots__/literal_one_of_test.ts.snap deleted file mode 100644 index 0bdf47c..0000000 --- a/is/__snapshots__/literal_one_of_test.ts.snap +++ /dev/null @@ -1,3 +0,0 @@ -export const snapshot = {}; - -snapshot[`isLiteralOneOf > returns properly named function 1`] = `'isLiteralOneOf(["hello", "world"])'`; diff --git a/is/__snapshots__/map_of_test.ts.snap b/is/__snapshots__/map_of_test.ts.snap deleted file mode 100644 index 1f0a965..0000000 --- a/is/__snapshots__/map_of_test.ts.snap +++ /dev/null @@ -1,9 +0,0 @@ -export const snapshot = {}; - -snapshot[`isMapOf > returns properly named function 1`] = `"isMapOf(isNumber, undefined)"`; - -snapshot[`isMapOf > returns properly named function 2`] = `"isMapOf((anonymous), undefined)"`; - -snapshot[`isMapOf > returns properly named function 1`] = `"isMapOf(isNumber, isString)"`; - -snapshot[`isMapOf > returns properly named function 2`] = `"isMapOf((anonymous), isString)"`; diff --git a/is/__snapshots__/object_of_test.ts.snap b/is/__snapshots__/object_of_test.ts.snap index c915e6d..7524ffc 100644 --- a/is/__snapshots__/object_of_test.ts.snap +++ b/is/__snapshots__/object_of_test.ts.snap @@ -1,6 +1,6 @@ export const snapshot = {}; -snapshot[`isObjectOf > returns properly named function 1`] = ` +snapshot[`isObjectOf > returns properly named predicate function 1`] = ` "isObjectOf({ a: isNumber, b: isString, @@ -8,9 +8,9 @@ snapshot[`isObjectOf > returns properly named function 1`] = ` })" `; -snapshot[`isObjectOf > returns properly named function 2`] = `"isObjectOf({a: a})"`; +snapshot[`isObjectOf > returns properly named predicate function 2`] = `"isObjectOf({a: a})"`; -snapshot[`isObjectOf > returns properly named function 3`] = ` +snapshot[`isObjectOf > returns properly named predicate function 3`] = ` "isObjectOf({ a: isObjectOf({ b: isObjectOf({c: isBoolean}) diff --git a/is/__snapshots__/omit_of_test.ts.snap b/is/__snapshots__/omit_of_test.ts.snap index dad991f..19c8629 100644 --- a/is/__snapshots__/omit_of_test.ts.snap +++ b/is/__snapshots__/omit_of_test.ts.snap @@ -1,10 +1,10 @@ export const snapshot = {}; -snapshot[`isOmitOf > returns properly named function 1`] = ` +snapshot[`isOmitOf > returns properly named predicate function 1`] = ` "isObjectOf({ a: isNumber, c: isBoolean })" `; -snapshot[`isOmitOf > returns properly named function 2`] = `"isObjectOf({a: isNumber})"`; +snapshot[`isOmitOf > returns properly named predicate function 2`] = `"isObjectOf({a: isNumber})"`; diff --git a/is/__snapshots__/parameters_of_test.ts.snap b/is/__snapshots__/parameters_of_test.ts.snap index e305ef2..d1de1ce 100644 --- a/is/__snapshots__/parameters_of_test.ts.snap +++ b/is/__snapshots__/parameters_of_test.ts.snap @@ -1,6 +1,6 @@ export const snapshot = {}; -snapshot[`isParametersOf > returns properly named function 1`] = ` +snapshot[`isParametersOf > returns properly named predicate function 1`] = ` "isParametersOf([ isNumber, isString, @@ -8,11 +8,11 @@ snapshot[`isParametersOf > returns properly named function 1`] = ` ])" `; -snapshot[`isParametersOf > returns properly named function 2`] = `"isParametersOf([(anonymous)])"`; +snapshot[`isParametersOf > returns properly named predicate function 2`] = `"isParametersOf([(anonymous)])"`; -snapshot[`isParametersOf > returns properly named function 3`] = `"isParametersOf([])"`; +snapshot[`isParametersOf > returns properly named predicate function 3`] = `"isParametersOf([])"`; -snapshot[`isParametersOf > returns properly named function 4`] = ` +snapshot[`isParametersOf > returns properly named predicate function 4`] = ` "isParametersOf([ isParametersOf([ isParametersOf([ @@ -24,7 +24,7 @@ snapshot[`isParametersOf > returns properly named function 4`] = ` ])" `; -snapshot[`isParametersOf > returns properly named function 1`] = ` +snapshot[`isParametersOf > returns properly named predicate function 1`] = ` "isParametersOf([ isNumber, isString, @@ -32,11 +32,11 @@ snapshot[`isParametersOf > returns properly named function 1`] = ` ], isArray)" `; -snapshot[`isParametersOf > returns properly named function 2`] = `"isParametersOf([(anonymous)], isArrayOf(isString))"`; +snapshot[`isParametersOf > returns properly named predicate function 2`] = `"isParametersOf([(anonymous)], isArrayOf(isString))"`; -snapshot[`isParametersOf > returns properly named function 3`] = `"isParametersOf([], isArrayOf(isString))"`; +snapshot[`isParametersOf > returns properly named predicate function 3`] = `"isParametersOf([], isArrayOf(isString))"`; -snapshot[`isParametersOf > returns properly named function 4`] = ` +snapshot[`isParametersOf > returns properly named predicate function 4`] = ` "isParametersOf([ isParametersOf([ isParametersOf([ diff --git a/is/__snapshots__/partial_of_test.ts.snap b/is/__snapshots__/partial_of_test.ts.snap index 315f88f..6f96fc2 100644 --- a/is/__snapshots__/partial_of_test.ts.snap +++ b/is/__snapshots__/partial_of_test.ts.snap @@ -1,6 +1,6 @@ export const snapshot = {}; -snapshot[`isPartialOf > returns properly named function 1`] = ` +snapshot[`isPartialOf > returns properly named predicate function 1`] = ` "isObjectOf({ a: asOptional(isNumber), b: asOptional(isUnionOf([ @@ -12,7 +12,7 @@ snapshot[`isPartialOf > returns properly named function 1`] = ` })" `; -snapshot[`isPartialOf > returns properly named function 2`] = ` +snapshot[`isPartialOf > returns properly named predicate function 2`] = ` "isObjectOf({ a: asOptional(isNumber), b: asOptional(isUnionOf([ diff --git a/is/__snapshots__/pick_of_test.ts.snap b/is/__snapshots__/pick_of_test.ts.snap index f76fbb4..911dc0e 100644 --- a/is/__snapshots__/pick_of_test.ts.snap +++ b/is/__snapshots__/pick_of_test.ts.snap @@ -1,10 +1,10 @@ export const snapshot = {}; -snapshot[`isPickOf > returns properly named function 1`] = ` +snapshot[`isPickOf > returns properly named predicate function 1`] = ` "isObjectOf({ a: isNumber, c: isBoolean })" `; -snapshot[`isPickOf > returns properly named function 2`] = `"isObjectOf({a: isNumber})"`; +snapshot[`isPickOf > returns properly named predicate function 2`] = `"isObjectOf({a: isNumber})"`; diff --git a/is/__snapshots__/readonly_of_test.ts.snap b/is/__snapshots__/readonly_of_test.ts.snap index 54c352d..308a72d 100644 --- a/is/__snapshots__/readonly_of_test.ts.snap +++ b/is/__snapshots__/readonly_of_test.ts.snap @@ -1,10 +1,10 @@ export const snapshot = {}; -snapshot[`isReadonlyOf > with isRecord > returns properly named function 1`] = `"isReadonlyOf(isRecord)"`; +snapshot[`isReadonlyOf > with isRecord > returns properly named predicate function 1`] = `"isReadonlyOf(isRecord)"`; -snapshot[`isReadonlyOf > with isRecord > returns properly named function 2`] = `"isReadonlyOf(isRecord)"`; +snapshot[`isReadonlyOf > with isRecord > returns properly named predicate function 2`] = `"isReadonlyOf(isRecord)"`; -snapshot[`isReadonlyOf > with isObjectOf > returns properly named function 1`] = ` +snapshot[`isReadonlyOf > with isObjectOf > returns properly named predicate function 1`] = ` "isReadonlyOf(isObjectOf({ a: isNumber, b: isUnionOf([ @@ -15,7 +15,7 @@ snapshot[`isReadonlyOf > with isObjectOf > returns properly named function 1` }))" `; -snapshot[`isReadonlyOf > with isObjectOf > returns properly named function 2`] = ` +snapshot[`isReadonlyOf > with isObjectOf > returns properly named predicate function 2`] = ` "isReadonlyOf(isObjectOf({ a: isNumber, b: isUnionOf([ @@ -26,7 +26,7 @@ snapshot[`isReadonlyOf > with isObjectOf > returns properly named function 2` }))" `; -snapshot[`isReadonlyOf > with isTupleOf > returns properly named function 1`] = ` +snapshot[`isReadonlyOf > with isTupleOf > returns properly named predicate function 1`] = ` "isReadonlyOf(isTupleOf([ isNumber, isString, @@ -34,7 +34,7 @@ snapshot[`isReadonlyOf > with isTupleOf > returns properly named function 1`] ]))" `; -snapshot[`isReadonlyOf > with isTupleOf > returns properly named function 2`] = ` +snapshot[`isReadonlyOf > with isTupleOf > returns properly named predicate function 2`] = ` "isReadonlyOf(isTupleOf([ isNumber, isString, @@ -42,6 +42,6 @@ snapshot[`isReadonlyOf > with isTupleOf > returns properly named function 2`] ]))" `; -snapshot[`isReadonlyOf > with isUniformTupleOf > returns properly named function 1`] = `"isReadonlyOf(isUniformTupleOf(3, isNumber))"`; +snapshot[`isReadonlyOf > with isUniformTupleOf > returns properly named predicate function 1`] = `"isReadonlyOf(isUniformTupleOf(3, isNumber))"`; -snapshot[`isReadonlyOf > with isUniformTupleOf > returns properly named function 2`] = `"isReadonlyOf(isUniformTupleOf(3, isNumber))"`; +snapshot[`isReadonlyOf > with isUniformTupleOf > returns properly named predicate function 2`] = `"isReadonlyOf(isUniformTupleOf(3, isNumber))"`; diff --git a/is/__snapshots__/record_object_of_test.ts.snap b/is/__snapshots__/record_object_of_test.ts.snap index d62a5d2..1254e9f 100644 --- a/is/__snapshots__/record_object_of_test.ts.snap +++ b/is/__snapshots__/record_object_of_test.ts.snap @@ -1,9 +1,9 @@ export const snapshot = {}; -snapshot[`isRecordObjectOf > returns properly named function 1`] = `"isRecordObjectOf(isNumber, undefined)"`; +snapshot[`isRecordObjectOf > returns properly named predicate function 1`] = `"isRecordObjectOf(isNumber, undefined)"`; -snapshot[`isRecordObjectOf > returns properly named function 2`] = `"isRecordObjectOf((anonymous), undefined)"`; +snapshot[`isRecordObjectOf > returns properly named predicate function 2`] = `"isRecordObjectOf((anonymous), undefined)"`; -snapshot[`isRecordObjectOf > returns properly named function 1`] = `"isRecordObjectOf(isNumber, isString)"`; +snapshot[`isRecordObjectOf > returns properly named predicate function 1`] = `"isRecordObjectOf(isNumber, isString)"`; -snapshot[`isRecordObjectOf > returns properly named function 2`] = `"isRecordObjectOf((anonymous), isString)"`; +snapshot[`isRecordObjectOf > returns properly named predicate function 2`] = `"isRecordObjectOf((anonymous), isString)"`; diff --git a/is/__snapshots__/record_of_test.ts.snap b/is/__snapshots__/record_of_test.ts.snap index 90eeadd..aa1da92 100644 --- a/is/__snapshots__/record_of_test.ts.snap +++ b/is/__snapshots__/record_of_test.ts.snap @@ -1,9 +1,9 @@ export const snapshot = {}; -snapshot[`isRecordOf > returns properly named function 1`] = `"isRecordOf(isNumber, undefined)"`; +snapshot[`isRecordOf > returns properly named predicate function 1`] = `"isRecordOf(isNumber, undefined)"`; -snapshot[`isRecordOf > returns properly named function 2`] = `"isRecordOf((anonymous), undefined)"`; +snapshot[`isRecordOf > returns properly named predicate function 2`] = `"isRecordOf((anonymous), undefined)"`; -snapshot[`isRecordOf > returns properly named function 1`] = `"isRecordOf(isNumber, isString)"`; +snapshot[`isRecordOf > returns properly named predicate function 1`] = `"isRecordOf(isNumber, isString)"`; -snapshot[`isRecordOf > returns properly named function 2`] = `"isRecordOf((anonymous), isString)"`; +snapshot[`isRecordOf > returns properly named predicate function 2`] = `"isRecordOf((anonymous), isString)"`; diff --git a/is/__snapshots__/required_of_test.ts.snap b/is/__snapshots__/required_of_test.ts.snap index a858a1a..7c30fac 100644 --- a/is/__snapshots__/required_of_test.ts.snap +++ b/is/__snapshots__/required_of_test.ts.snap @@ -1,6 +1,6 @@ export const snapshot = {}; -snapshot[`isRequiredOf > returns properly named function 1`] = ` +snapshot[`isRequiredOf > returns properly named predicate function 1`] = ` "isObjectOf({ a: isNumber, b: isUnionOf([ @@ -12,7 +12,7 @@ snapshot[`isRequiredOf > returns properly named function 1`] = ` })" `; -snapshot[`isRequiredOf > returns properly named function 2`] = ` +snapshot[`isRequiredOf > returns properly named predicate function 2`] = ` "isObjectOf({ a: isNumber, b: isUnionOf([ diff --git a/is/__snapshots__/set_of_test.ts.snap b/is/__snapshots__/set_of_test.ts.snap index 66104bd..b1dc926 100644 --- a/is/__snapshots__/set_of_test.ts.snap +++ b/is/__snapshots__/set_of_test.ts.snap @@ -1,5 +1,5 @@ export const snapshot = {}; -snapshot[`isSetOf > returns properly named function 1`] = `"isSetOf(isNumber)"`; +snapshot[`isSetOf > returns properly named predicate function 1`] = `"isSetOf(isNumber)"`; -snapshot[`isSetOf > returns properly named function 2`] = `"isSetOf((anonymous))"`; +snapshot[`isSetOf > returns properly named predicate function 2`] = `"isSetOf((anonymous))"`; diff --git a/is/__snapshots__/strict_of_test.ts.snap b/is/__snapshots__/strict_of_test.ts.snap index 597e1e7..add9027 100644 --- a/is/__snapshots__/strict_of_test.ts.snap +++ b/is/__snapshots__/strict_of_test.ts.snap @@ -1,6 +1,6 @@ export const snapshot = {}; -snapshot[`isStrictOf > returns properly named function 1`] = ` +snapshot[`isStrictOf > returns properly named predicate function 1`] = ` "isStrictOf(isObjectOf({ a: isNumber, b: isString, @@ -8,9 +8,9 @@ snapshot[`isStrictOf > returns properly named function 1`] = ` }))" `; -snapshot[`isStrictOf > returns properly named function 2`] = `"isStrictOf(isObjectOf({a: a}))"`; +snapshot[`isStrictOf > returns properly named predicate function 2`] = `"isStrictOf(isObjectOf({a: a}))"`; -snapshot[`isStrictOf > returns properly named function 3`] = ` +snapshot[`isStrictOf > returns properly named predicate function 3`] = ` "isStrictOf(isObjectOf({ a: isStrictOf(isObjectOf({ b: isStrictOf(isObjectOf({c: isBoolean})) diff --git a/is/__snapshots__/tuple_of_test.ts.snap b/is/__snapshots__/tuple_of_test.ts.snap index 5673452..2098ae2 100644 --- a/is/__snapshots__/tuple_of_test.ts.snap +++ b/is/__snapshots__/tuple_of_test.ts.snap @@ -1,6 +1,6 @@ export const snapshot = {}; -snapshot[`isTupleOf > returns properly named function 1`] = ` +snapshot[`isTupleOf > returns properly named predicate function 1`] = ` "isTupleOf([ isNumber, isString, @@ -8,9 +8,9 @@ snapshot[`isTupleOf > returns properly named function 1`] = ` ])" `; -snapshot[`isTupleOf > returns properly named function 2`] = `"isTupleOf([(anonymous)])"`; +snapshot[`isTupleOf > returns properly named predicate function 2`] = `"isTupleOf([(anonymous)])"`; -snapshot[`isTupleOf > returns properly named function 3`] = ` +snapshot[`isTupleOf > returns properly named predicate function 3`] = ` "isTupleOf([ isTupleOf([ isTupleOf([ @@ -22,7 +22,7 @@ snapshot[`isTupleOf > returns properly named function 3`] = ` ])" `; -snapshot[`isTupleOf > returns properly named function 1`] = ` +snapshot[`isTupleOf > returns properly named predicate function 1`] = ` "isTupleOf([ isNumber, isString, @@ -30,9 +30,9 @@ snapshot[`isTupleOf > returns properly named function 1`] = ` ], isArray)" `; -snapshot[`isTupleOf > returns properly named function 2`] = `"isTupleOf([(anonymous)], isArrayOf(isString))"`; +snapshot[`isTupleOf > returns properly named predicate function 2`] = `"isTupleOf([(anonymous)], isArrayOf(isString))"`; -snapshot[`isTupleOf > returns properly named function 3`] = ` +snapshot[`isTupleOf > returns properly named predicate function 3`] = ` "isTupleOf([ isTupleOf([ isTupleOf([ diff --git a/is/__snapshots__/uniform_tuple_of_test.ts.snap b/is/__snapshots__/uniform_tuple_of_test.ts.snap index 8f13f88..5f32b7c 100644 --- a/is/__snapshots__/uniform_tuple_of_test.ts.snap +++ b/is/__snapshots__/uniform_tuple_of_test.ts.snap @@ -1,7 +1,7 @@ export const snapshot = {}; -snapshot[`isUniformTupleOf > returns properly named function 1`] = `"isUniformTupleOf(3, undefined)"`; +snapshot[`isUniformTupleOf > returns properly named predicate function 1`] = `"isUniformTupleOf(3, undefined)"`; -snapshot[`isUniformTupleOf > returns properly named function 2`] = `"isUniformTupleOf(3, isNumber)"`; +snapshot[`isUniformTupleOf > returns properly named predicate function 2`] = `"isUniformTupleOf(3, isNumber)"`; -snapshot[`isUniformTupleOf > returns properly named function 3`] = `"isUniformTupleOf(3, (anonymous))"`; +snapshot[`isUniformTupleOf > returns properly named predicate function 3`] = `"isUniformTupleOf(3, (anonymous))"`; diff --git a/is/__snapshots__/union_of_test.ts.snap b/is/__snapshots__/union_of_test.ts.snap index cc9cb3a..db9ae3f 100644 --- a/is/__snapshots__/union_of_test.ts.snap +++ b/is/__snapshots__/union_of_test.ts.snap @@ -1,6 +1,6 @@ export const snapshot = {}; -snapshot[`isUnionOf > returns properly named function 1`] = ` +snapshot[`isUnionOf > returns properly named predicate function 1`] = ` "isUnionOf([ isNumber, isString, diff --git a/is/any.ts b/is/any.ts index a993a9d..e3a177a 100644 --- a/is/any.ts +++ b/is/any.ts @@ -1,6 +1,8 @@ /** * Assume `x is `any` and always return `true` regardless of the type of `x`. * + * Use {@linkcode isUnknown} to assume that a value is `unknown`. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/array.ts b/is/array.ts index 2132acd..9921c1d 100644 --- a/is/array.ts +++ b/is/array.ts @@ -1,6 +1,8 @@ /** * Return `true` if the type of `x` is `unknown[]`. * + * Use {@linkcode isArrayOf} to check if the type of `x` is an array of `T`. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/array_of.ts b/is/array_of.ts index e411282..e9b91a7 100644 --- a/is/array_of.ts +++ b/is/array_of.ts @@ -5,6 +5,8 @@ import { isArray } from "./array.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `T[]`. * + * Use {@linkcode isArray} to check if the type of `x` is an array of `unknown`. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts diff --git a/is/array_of_test.ts b/is/array_of_test.ts index 0be24d5..2944a77 100644 --- a/is/array_of_test.ts +++ b/is/array_of_test.ts @@ -1,32 +1,36 @@ import { assertEquals } from "@std/assert"; -import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { isArrayOf } from "./array_of.ts"; Deno.test("isArrayOf", async (t) => { - await t.step("returns properly named function", async (t) => { - await assertSnapshot(t, isArrayOf(is.Number).name); - await assertSnapshot(t, isArrayOf((_x): _x is string => false).name); - }); - await t.step("returns proper type predicate", () => { - const a: unknown = [0, 1, 2]; - if (isArrayOf(is.Number)(a)) { - assertType>(true); - } + await t.step("returns properly named predicate function", () => { + assertEquals(typeof isArrayOf(is.Number), "function"); + assertEquals(isArrayOf(is.Number).name, "isArrayOf(isNumber)"); + assertEquals( + isArrayOf((_x): _x is unknown => true).name, + "isArrayOf((anonymous))", + ); }); + await t.step("returns true on T array", () => { assertEquals(isArrayOf(is.Number)([0, 1, 2]), true); assertEquals(isArrayOf(is.String)(["a", "b", "c"]), true); assertEquals(isArrayOf(is.Boolean)([true, false, true]), true); }); + await t.step("returns false on non T array", () => { assertEquals(isArrayOf(is.String)([0, 1, 2]), false); assertEquals(isArrayOf(is.Number)(["a", "b", "c"]), false); assertEquals(isArrayOf(is.String)([true, false, true]), false); }); - await testWithExamples(t, isArrayOf((_: unknown): _ is unknown => true), { - excludeExamples: ["array"], + + await t.step("predicated type is correct", () => { + const a: unknown = undefined; + + if (isArrayOf(is.Number)(a)) { + assertType>(true); + } }); }); diff --git a/is/async_function.ts b/is/async_function.ts index e63ca61..78db3eb 100644 --- a/is/async_function.ts +++ b/is/async_function.ts @@ -3,6 +3,9 @@ const objectToString = Object.prototype.toString; /** * Return `true` if the type of `x` is `function` (async function). * + * Use {@linkcode isFunction} to check if the type of `x` is a function. + * Use {@linkcode isSyncFunction} to check if the type of `x` is a synchronous function. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/function.ts b/is/function.ts index e42400f..9b6cc71 100644 --- a/is/function.ts +++ b/is/function.ts @@ -1,6 +1,9 @@ /** * Return `true` if the type of `x` is `function`. * + * Use {@linkcode isSyncFunction} to check if the type of `x` is a synchronous function. + * Use {@linkcode isAsyncFunction} to check if the type of `x` is an asynchronous function. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/instance_of_test.ts b/is/instance_of_test.ts index 2d45d1b..a8fa635 100644 --- a/is/instance_of_test.ts +++ b/is/instance_of_test.ts @@ -1,47 +1,43 @@ import { assertEquals } from "@std/assert"; -import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { isInstanceOf } from "./instance_of.ts"; Deno.test("isInstanceOf", async (t) => { - await t.step("returns properly named function", async (t) => { - await assertSnapshot(t, isInstanceOf(Date).name); - await assertSnapshot(t, isInstanceOf(class {}).name); + await t.step("returns properly named predicate function", () => { + assertEquals(typeof isInstanceOf(Date), "function"); + assertEquals(isInstanceOf(Date).name, "isInstanceOf(Date)"); + assertEquals(isInstanceOf(class {}).name, "isInstanceOf((anonymous))"); }); + await t.step("returns true on T instance", () => { class Cls {} assertEquals(isInstanceOf(Cls)(new Cls()), true); assertEquals(isInstanceOf(Date)(new Date()), true); assertEquals(isInstanceOf(Promise)(new Promise(() => {})), true); }); - await t.step("with user-defined class", async (t) => { + + await t.step("returns false on non T instance", () => { class Cls {} - await testWithExamples(t, isInstanceOf(Cls)); - }); - await t.step("with Date", async (t) => { - await testWithExamples(t, isInstanceOf(Date), { validExamples: ["date"] }); + assertEquals(isInstanceOf(Date)(new Cls()), false); + assertEquals(isInstanceOf(Promise)(new Date()), false); + assertEquals(isInstanceOf(Cls)(new Promise(() => {})), false); }); - await t.step("with Promise", async (t) => { - await testWithExamples(t, isInstanceOf(Promise), { - validExamples: ["promise"], - }); - }); - await t.step("returns proper type predicate", () => { + + await t.step("predicated type is correct", () => { class Cls {} - const a: unknown = new Cls(); + const a: unknown = undefined; + if (isInstanceOf(Cls)(a)) { assertType>(true); } - const b: unknown = new Date(); - if (isInstanceOf(Date)(b)) { - assertType>(true); + if (isInstanceOf(Date)(a)) { + assertType>(true); } - const c: unknown = new Promise(() => {}); - if (isInstanceOf(Promise)(c)) { - assertType>>(true); + if (isInstanceOf(Promise)(a)) { + assertType>>(true); } }); }); diff --git a/is/intersection_of.ts b/is/intersection_of.ts index 47af3bb..0b748d8 100644 --- a/is/intersection_of.ts +++ b/is/intersection_of.ts @@ -1,11 +1,13 @@ import { rewriteName } from "../_funcutil.ts"; -import { hasAnnotation, type WithPredObj } from "../_annotation.ts"; +import { hasAnnotation, type IsPredObj } from "../_annotation.ts"; import type { Predicate } from "../type.ts"; import { isObjectOf } from "./object_of.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `IntersectionOf`. * + * Use {@linkcode isUnionOf} to check if the type of `x` is a union of `T`. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts @@ -40,17 +42,14 @@ import { isObjectOf } from "./object_of.ts"; */ export function isIntersectionOf< T extends readonly [ - Predicate & WithPredObj>>, - ...( - & Predicate - & WithPredObj>> - )[], + Predicate & IsPredObj, + ...(Predicate & IsPredObj)[], ], >( preds: T, ): & Predicate> - & WithPredObj>>; + & IsPredObj; export function isIntersectionOf< T extends readonly [Predicate], >( @@ -62,7 +61,7 @@ export function isIntersectionOf< preds: T, ): & Predicate> - & WithPredObj>>; + & IsPredObj; export function isIntersectionOf< T extends readonly [Predicate, ...Predicate[]], >( @@ -70,7 +69,7 @@ export function isIntersectionOf< ): | Predicate | Predicate> - & WithPredObj>> { + & IsPredObj { const predObj = {}; const restPreds = preds.filter((pred) => { if (!hasAnnotation(pred, "predObj")) { diff --git a/is/intersection_of_test.ts b/is/intersection_of_test.ts index 56ead45..a22c4f7 100644 --- a/is/intersection_of_test.ts +++ b/is/intersection_of_test.ts @@ -1,52 +1,53 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { isIntersectionOf } from "./intersection_of.ts"; Deno.test("isIntersectionOf", async (t) => { - await t.step("returns properly named function", async (t) => { - await assertSnapshot( - t, - isIntersectionOf([ - is.ObjectOf({ a: is.Number }), - is.ObjectOf({ b: is.String }), - ]).name, - "Should return `isObjectOf`, if all predicates that", - ); - await assertSnapshot( - t, - isIntersectionOf([ - is.String, - ]).name, - "Should return as is, if there is only one predicate", - ); - await assertSnapshot( - t, - isIntersectionOf([ - is.Function, - is.ObjectOf({ b: is.String }), - ]).name, - ); + const objPreds = [ + is.ObjectOf({ a: is.Number }), + is.ObjectOf({ b: is.String }), + ] as const; + const mixPreds = [ + is.Function, + is.ObjectOf({ b: is.String }), + ] as const; + + await t.step("returns properly named predicate function", async (t) => { + assertEquals(typeof isIntersectionOf([is.String]), "function"); + await assertSnapshot(t, isIntersectionOf([is.String]).name); + await assertSnapshot(t, isIntersectionOf(objPreds).name); + await assertSnapshot(t, isIntersectionOf(mixPreds).name); }); - await t.step("returns proper type predicate", () => { - const objPreds = [ - is.ObjectOf({ a: is.Number }), - is.ObjectOf({ b: is.String }), - ] as const; - const funcPreds = [ - is.Function, - is.ObjectOf({ b: is.String }), - ] as const; - const a: unknown = { a: 0, b: "a" }; - if (isIntersectionOf(objPreds)(a)) { - assertType>(true); - } + + await t.step("returns true on all of T", () => { + const f = Object.assign(() => void 0, { b: "a" }); + assertEquals(isIntersectionOf([is.String])("a"), true); + assertEquals(isIntersectionOf(objPreds)({ a: 0, b: "a" }), true); + assertEquals(isIntersectionOf(mixPreds)(f), true); + }); + + await t.step("returns false on non of T", () => { + const f = Object.assign(() => void 0, { b: "a" }); + assertEquals(isIntersectionOf(objPreds)("a"), false); + assertEquals(isIntersectionOf(mixPreds)({ a: 0, b: "a" }), false); + assertEquals(isIntersectionOf([is.String])(f), false); + }); + + await t.step("predicated type is correct", () => { + const a: unknown = undefined; + if (isIntersectionOf([is.String])(a)) { assertType>(true); } - if (isIntersectionOf(funcPreds)(a)) { + + if (isIntersectionOf(objPreds)(a)) { + assertType>(true); + } + + if (isIntersectionOf(mixPreds)(a)) { assertType< Equal< typeof a, @@ -56,80 +57,24 @@ Deno.test("isIntersectionOf", async (t) => { >(true); } }); - await t.step("returns true on all of T", () => { - const objPreds = [ - is.ObjectOf({ a: is.Number }), - is.ObjectOf({ b: is.String }), - ] as const; - const funcPreds = [ - is.Function, - is.ObjectOf({ b: is.String }), - ] as const; - const f = Object.assign(() => void 0, { b: "a" }); - assertEquals(isIntersectionOf(objPreds)({ a: 0, b: "a" }), true); - assertEquals(isIntersectionOf([is.String])("a"), true); - assertEquals(isIntersectionOf(funcPreds)(f), true); - }); - await t.step("returns false on non of T", async (t) => { - const preds = [ - is.ObjectOf({ a: is.Number }), - is.ObjectOf({ b: is.String }), - ] as const; - assertEquals( - isIntersectionOf(preds)({ a: 0, b: 0 }), - false, - "Some properties has wrong type", - ); - assertEquals( - isIntersectionOf(preds)({ a: 0 }), - false, - "Some properties does not exists", - ); - await testWithExamples(t, isIntersectionOf(preds), { - excludeExamples: ["record"], - }); - }); - await t.step("returns false on non of T with any predicates", async (t) => { - const preds = [ - is.Function, - is.ObjectOf({ b: is.String }), - ] as const; - assertEquals( - isIntersectionOf(preds)({ b: "a" }), - false, - "Not a function object", - ); - assertEquals( - isIntersectionOf(preds)(() => void 0), - false, - "Some properties does not exists in Function object", - ); - await testWithExamples(t, isIntersectionOf(preds), { - excludeExamples: ["record"], - }); - }); - await t.step("asdf", async (t) => { - const preds = [ - is.ObjectOf({ a: is.String }), - is.ObjectOf({ b: is.String }), - ] as const; - assertEquals( - is.PickOf(isIntersectionOf(preds), ["a"])({ a: "a" }), - true, - "All properties has correct type", - ); - assertEquals( - isIntersectionOf(preds)({ b: "a" }), - false, - "Not a function object", - ); - assertEquals( - isIntersectionOf(preds)(() => void 0), - false, - "Some properties does not exists in Function object", - ); - await testWithExamples(t, isIntersectionOf(preds), { - excludeExamples: ["record"], - }); + + await t.step("predicated type is correct (#68)", () => { + const a: unknown = undefined; + const pred = isIntersectionOf([ + is.ObjectOf({ id: is.String }), + is.UnionOf([ + is.ObjectOf({ result: is.String }), + is.ObjectOf({ error: is.String }), + ]), + ]); + + if (pred(a)) { + assertType< + Equal< + typeof a, + { id: string } & ({ result: string } | { error: string }) + > + >(true); + } }); }); diff --git a/is/literal_of.ts b/is/literal_of.ts index b7d2474..1388675 100644 --- a/is/literal_of.ts +++ b/is/literal_of.ts @@ -4,6 +4,9 @@ import type { Predicate, Primitive } from "../type.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is a literal type of `pred`. * + * Use {@linkcode isLiteral} to check if the type of `x` is a literal type. + * Use {@linkcode isLiteralOneOf} to check if the type of `x` is one of the literal type of `Primitive[]`. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts diff --git a/is/literal_of_test.ts b/is/literal_of_test.ts index 424d828..f8a9b75 100644 --- a/is/literal_of_test.ts +++ b/is/literal_of_test.ts @@ -1,32 +1,79 @@ import { assertEquals } from "@std/assert"; -import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { isLiteralOf } from "./literal_of.ts"; Deno.test("isLiteralOf", async (t) => { - await t.step("returns properly named function", async (t) => { - await assertSnapshot(t, isLiteralOf("hello").name); - await assertSnapshot(t, isLiteralOf(100).name); - await assertSnapshot(t, isLiteralOf(100n).name); - await assertSnapshot(t, isLiteralOf(true).name); - await assertSnapshot(t, isLiteralOf(null).name); - await assertSnapshot(t, isLiteralOf(undefined).name); - await assertSnapshot(t, isLiteralOf(Symbol("asdf")).name); - }); - await t.step("returns proper type predicate", () => { - const pred = "hello"; - const a: unknown = "hello"; - if (isLiteralOf(pred)(a)) { - assertType>(true); - } + await t.step("returns properly named predicate function", () => { + assertEquals(typeof isLiteralOf("hello"), "function"); + assertEquals(isLiteralOf("hello").name, `isLiteralOf("hello")`); + assertEquals(isLiteralOf(100).name, `isLiteralOf(100)`); + assertEquals(isLiteralOf(100n).name, `isLiteralOf(100n)`); + assertEquals(isLiteralOf(true).name, `isLiteralOf(true)`); + assertEquals(isLiteralOf(false).name, `isLiteralOf(false)`); + assertEquals(isLiteralOf(null).name, `isLiteralOf(null)`); + assertEquals(isLiteralOf(undefined).name, `isLiteralOf(undefined)`); + assertEquals(isLiteralOf(Symbol("asdf")).name, `isLiteralOf(Symbol(asdf))`); }); + await t.step("returns true on literal T", () => { - const pred = "hello"; - assertEquals(isLiteralOf(pred)("hello"), true); + const s = Symbol("asdf"); + assertEquals(isLiteralOf("hello")("hello"), true); + assertEquals(isLiteralOf(100)(100), true); + assertEquals(isLiteralOf(100n)(100n), true); + assertEquals(isLiteralOf(true)(true), true); + assertEquals(isLiteralOf(false)(false), true); + assertEquals(isLiteralOf(null)(null), true); + assertEquals(isLiteralOf(undefined)(undefined), true); + assertEquals(isLiteralOf(s)(s), true); + }); + + await t.step("returns false on non literal T", () => { + const s = Symbol("asdf"); + assertEquals(isLiteralOf(100)("hello"), false); + assertEquals(isLiteralOf(100n)(100), false); + assertEquals(isLiteralOf(true)(100n), false); + assertEquals(isLiteralOf(false)(true), false); + assertEquals(isLiteralOf(null)(false), false); + assertEquals(isLiteralOf(undefined)(null), false); + assertEquals(isLiteralOf(s)(undefined), false); + assertEquals(isLiteralOf("hello")(s), false); }); - await t.step("returns false on non literal T", async (t) => { - const pred = "hello"; - await testWithExamples(t, isLiteralOf(pred)); + + await t.step("predicated type is correct", () => { + const s = Symbol("asdf"); + const a: unknown = undefined; + + if (isLiteralOf("hello")(a)) { + assertType>(true); + } + + if (isLiteralOf(100)(a)) { + assertType>(true); + } + + if (isLiteralOf(100n)(a)) { + assertType>(true); + } + + if (isLiteralOf(true)(a)) { + assertType>(true); + } + + if (isLiteralOf(false)(a)) { + assertType>(true); + } + + if (isLiteralOf(null)(a)) { + assertType>(true); + } + + if (isLiteralOf(undefined)(a)) { + assertType>(true); + } + + if (isLiteralOf(s)(a)) { + assertType>(true); + } }); }); diff --git a/is/literal_one_of.ts b/is/literal_one_of.ts index a155311..b60547b 100644 --- a/is/literal_one_of.ts +++ b/is/literal_one_of.ts @@ -4,6 +4,9 @@ import type { Predicate, Primitive } from "../type.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is one of literal type in `preds`. * + * Use {@linkcode isLiteral} to check if the type of `x` is a literal type. + * Use {@linkcode isLiteralOf} to check if the type of `x` is a literal type of `Primitive`. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts diff --git a/is/literal_one_of_test.ts b/is/literal_one_of_test.ts index 93d77f7..ecea097 100644 --- a/is/literal_one_of_test.ts +++ b/is/literal_one_of_test.ts @@ -1,27 +1,32 @@ import { assertEquals } from "@std/assert"; -import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { isLiteralOneOf } from "./literal_one_of.ts"; Deno.test("isLiteralOneOf", async (t) => { - await t.step("returns properly named function", async (t) => { - await assertSnapshot(t, isLiteralOneOf(["hello", "world"]).name); + const literals = ["hello", "world"] as const; + await t.step("returns properly named predicate function", () => { + assertEquals(typeof isLiteralOneOf(literals), "function"); + assertEquals( + isLiteralOneOf(literals).name, + `isLiteralOneOf(["hello", "world"])`, + ); }); + + await t.step("returns true on literal T", () => { + assertEquals(isLiteralOneOf(literals)("hello"), true); + assertEquals(isLiteralOneOf(literals)("world"), true); + }); + + await t.step("returns false on non literal T", () => { + assertEquals(isLiteralOneOf(literals)(""), false); + assertEquals(isLiteralOneOf(literals)(100), false); + }); + await t.step("returns proper type predicate", () => { - const preds = ["hello", "world"] as const; const a: unknown = "hello"; - if (isLiteralOneOf(preds)(a)) { + if (isLiteralOneOf(literals)(a)) { assertType>(true); } }); - await t.step("returns true on literal T", () => { - const preds = ["hello", "world"] as const; - assertEquals(isLiteralOneOf(preds)("hello"), true); - assertEquals(isLiteralOneOf(preds)("world"), true); - }); - await t.step("returns false on non literal T", async (t) => { - const preds = ["hello", "world"] as const; - await testWithExamples(t, isLiteralOneOf(preds)); - }); }); diff --git a/is/map.ts b/is/map.ts index ed579d6..545a993 100644 --- a/is/map.ts +++ b/is/map.ts @@ -1,6 +1,8 @@ /** * Return `true` if the type of `x` is `Map`. * + * Use {@linkcode isMapOf} to check if the type of `x` is a map of `T`. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/map_of.ts b/is/map_of.ts index f30f64f..cf4bc68 100644 --- a/is/map_of.ts +++ b/is/map_of.ts @@ -5,6 +5,8 @@ import { isMap } from "./map.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `Map`. * + * Use {@linkcode isMap} to check if the type of `x` is a map of `unknown`. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts @@ -36,8 +38,7 @@ export function isMapOf( return rewriteName( (x: unknown): x is Map => { if (!isMap(x)) return false; - for (const entry of x.entries()) { - const [k, v] = entry; + for (const [k, v] of x.entries()) { if (!pred(v)) return false; if (predKey && !predKey(k)) return false; } diff --git a/is/map_of_test.ts b/is/map_of_test.ts index 1b6d60f..2ebb16f 100644 --- a/is/map_of_test.ts +++ b/is/map_of_test.ts @@ -1,66 +1,74 @@ import { assertEquals } from "@std/assert"; -import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { isMapOf } from "./map_of.ts"; Deno.test("isMapOf", async (t) => { - await t.step("returns properly named function", async (t) => { - await assertSnapshot(t, isMapOf(is.Number).name); - await assertSnapshot(t, isMapOf((_x): _x is string => false).name); - }); - await t.step("returns proper type predicate", () => { - const a: unknown = new Map([["a", 0]]); - if (isMapOf(is.Number)(a)) { - assertType>>(true); - } + await t.step("returns properly named predicate function", () => { + assertEquals(typeof isMapOf(is.Number), "function"); + assertEquals(isMapOf(is.Number).name, "isMapOf(isNumber, undefined)"); + assertEquals( + isMapOf((_x): _x is unknown => true).name, + "isMapOf((anonymous), undefined)", + ); }); + await t.step("returns true on T map", () => { assertEquals(isMapOf(is.Number)(new Map([["a", 0]])), true); assertEquals(isMapOf(is.String)(new Map([["a", "a"]])), true); assertEquals(isMapOf(is.Boolean)(new Map([["a", true]])), true); }); + await t.step("returns false on non T map", () => { assertEquals(isMapOf(is.String)(new Map([["a", 0]])), false); assertEquals(isMapOf(is.Number)(new Map([["a", "a"]])), false); assertEquals(isMapOf(is.String)(new Map([["a", true]])), false); }); - await testWithExamples(t, isMapOf((_: unknown): _ is unknown => true), { - excludeExamples: ["map"], + + await t.step("returns proper type predicate", () => { + const a: unknown = undefined; + if (isMapOf(is.Number)(a)) { + assertType>>(true); + } }); }); Deno.test("isMapOf", async (t) => { - await t.step("returns properly named function", async (t) => { - await assertSnapshot(t, isMapOf(is.Number, is.String).name); - await assertSnapshot( - t, - isMapOf((_x): _x is string => false, is.String).name, + await t.step("returns properly named predicate function", () => { + assertEquals(typeof isMapOf(is.Number, is.String), "function"); + assertEquals( + isMapOf(is.Number, is.String).name, + "isMapOf(isNumber, isString)", + ); + assertEquals( + isMapOf((_x): _x is unknown => true, is.String).name, + "isMapOf((anonymous), isString)", ); }); - await t.step("returns proper type predicate", () => { - const a: unknown = new Map([["a", 0]]); - if (isMapOf(is.Number, is.String)(a)) { - assertType>>(true); - } - }); + await t.step("returns true on T map", () => { assertEquals(isMapOf(is.Number, is.String)(new Map([["a", 0]])), true); assertEquals(isMapOf(is.String, is.String)(new Map([["a", "a"]])), true); assertEquals(isMapOf(is.Boolean, is.String)(new Map([["a", true]])), true); }); + await t.step("returns false on non T map", () => { assertEquals(isMapOf(is.String, is.String)(new Map([["a", 0]])), false); assertEquals(isMapOf(is.Number, is.String)(new Map([["a", "a"]])), false); assertEquals(isMapOf(is.String, is.String)(new Map([["a", true]])), false); }); + await t.step("returns false on non K map", () => { assertEquals(isMapOf(is.Number, is.Number)(new Map([["a", 0]])), false); assertEquals(isMapOf(is.String, is.Number)(new Map([["a", "a"]])), false); assertEquals(isMapOf(is.Boolean, is.Number)(new Map([["a", true]])), false); }); - await testWithExamples(t, isMapOf((_: unknown): _ is unknown => true), { - excludeExamples: ["map"], + + await t.step("predicated type is correct", () => { + const a: unknown = new Map([["a", 0]]); + if (isMapOf(is.Number, is.String)(a)) { + assertType>>(true); + } }); }); diff --git a/is/null.ts b/is/null.ts index 212a6b4..a4d8a15 100644 --- a/is/null.ts +++ b/is/null.ts @@ -1,6 +1,9 @@ /** * Return `true` if the type of `x` is `null`. * + * Use {@linkcode isUndefined} to check if the type of `x` is `undefined`. + * Use {@linkcode isNullish} to check if the type of `x` is `null` or `undefined`. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/nullish.ts b/is/nullish.ts index 1c0468a..d462fba 100644 --- a/is/nullish.ts +++ b/is/nullish.ts @@ -1,6 +1,9 @@ /** * Return `true` if the type of `x` is `null` or `undefined`. * + * Use {@linkcode isNull} to check if the type of `x` is `null`. + * Use {@linkcode isUndefined} to check if the type of `x` is `undefined`. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/object_of.ts b/is/object_of.ts index 4a931cb..6a7633c 100644 --- a/is/object_of.ts +++ b/is/object_of.ts @@ -4,21 +4,23 @@ import { annotate, type AsOptional, type AsReadonly, - type WithPredObj, + type IsPredObj, } from "../_annotation.ts"; import type { Predicate } from "../type.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `ObjectOf`. * - * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. + * Use {@linkcode isRecordOf} if you want to check if the type of `x` is a record of `T`. * - * If {@linkcode asOptional} is specified in the predicate function, the property becomes optional. - * If {@linkcode asReadonly} is specified in the predicate function, the property becomes readonly. + * If {@linkcode asOptional} is specified in the predicate function in `predObj`, the property becomes optional. + * If {@linkcode asReadonly} is specified in the predicate function in `predObj`, the property becomes readonly. * * The number of keys of `x` must be greater than or equal to the number of keys of `predObj`. * Use {@linkcode isStrictOf} if you want to check the exact number of keys. * + * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. + * * ```ts * import { as, is } from "@core/unknownutil"; * @@ -36,7 +38,7 @@ import type { Predicate } from "../type.ts"; */ export function isObjectOf< T extends Record>, ->(predObj: T): Predicate> & WithPredObj { +>(predObj: T): Predicate> & IsPredObj { return annotate( rewriteName( (x: unknown): x is ObjectOf => { diff --git a/is/object_of_test.ts b/is/object_of_test.ts index e951ef6..7379377 100644 --- a/is/object_of_test.ts +++ b/is/object_of_test.ts @@ -1,64 +1,46 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { as } from "../as/mod.ts"; import { isObjectOf } from "./object_of.ts"; Deno.test("isObjectOf", async (t) => { - await t.step("returns properly named function", async (t) => { - await assertSnapshot( - t, - isObjectOf({ a: is.Number, b: is.String, c: is.Boolean }).name, - ); + const predObj = { + a: is.Number, + b: is.String, + c: is.Boolean, + }; + + await t.step("returns properly named predicate function", async (t) => { + assertEquals(typeof isObjectOf({}), "function"); + await assertSnapshot(t, isObjectOf(predObj).name); await assertSnapshot( t, isObjectOf({ a: (_x): _x is string => false }).name, ); - // Nested await assertSnapshot( t, isObjectOf({ a: isObjectOf({ b: isObjectOf({ c: is.Boolean }) }) }).name, ); }); - await t.step("returns proper type predicate", () => { - const predObj = { - a: is.Number, - b: is.String, - c: is.Boolean, - }; - const a: unknown = { a: 0, b: "a", c: true }; - if (isObjectOf(predObj)(a)) { - assertType>(true); - } - }); + await t.step("returns true on T object", () => { - const predObj = { - a: is.Number, - b: is.String, - c: is.Boolean, - }; assertEquals(isObjectOf(predObj)({ a: 0, b: "a", c: true }), true); assertEquals( isObjectOf(predObj)({ a: 0, b: "a", c: true, d: "ignored" }), true, - "Object have an unknown property", ); assertEquals( isObjectOf(predObj)( Object.assign(() => void 0, { a: 0, b: "a", c: true }), ), true, - "Function object", ); }); + await t.step("returns false on non T object", () => { - const predObj = { - a: is.Number, - b: is.String, - c: is.Boolean, - }; assertEquals(isObjectOf(predObj)("a"), false, "Value is not an object"); assertEquals( isObjectOf(predObj)({ a: 0, b: "a", c: "" }), @@ -76,6 +58,7 @@ Deno.test("isObjectOf", async (t) => { "Value is not an object", ); }); + await t.step("returns true on T instance", () => { const date = new Date(); const predObj = { @@ -83,8 +66,9 @@ Deno.test("isObjectOf", async (t) => { }; assertEquals(isObjectOf(predObj)(date), true, "Value is not an object"); }); - await t.step("with asOptional/asReadonly", () => { - const predObj = { + + await t.step("predicated type is correct", () => { + const predObj2 = { a: as.Readonly(as.Optional(is.String)), b: as.Optional(as.Readonly(is.String)), c: as.Readonly(is.String), @@ -92,8 +76,13 @@ Deno.test("isObjectOf", async (t) => { e: as.Unreadonly(as.Unoptional(as.Readonly(as.Optional(is.String)))), f: as.Unoptional(as.Unreadonly(as.Optional(as.Readonly(is.String)))), }; - const a: unknown = undefined; + const a: unknown = { a: 0, b: "a", c: true }; + if (isObjectOf(predObj)(a)) { + assertType>(true); + } + + if (isObjectOf(predObj2)(a)) { assertType< Equal< typeof a, @@ -109,9 +98,4 @@ Deno.test("isObjectOf", async (t) => { >(true); } }); - await testWithExamples( - t, - isObjectOf({ a: (_: unknown): _ is unknown => false }), - { excludeExamples: ["record"] }, - ); }); diff --git a/is/omit_of.ts b/is/omit_of.ts index 610ef3f..6ef562d 100644 --- a/is/omit_of.ts +++ b/is/omit_of.ts @@ -1,11 +1,22 @@ import type { FlatType } from "../_typeutil.ts"; -import type { WithPredObj } from "../_annotation.ts"; +import type { IsPredObj } from "../_annotation.ts"; import type { Predicate } from "../type.ts"; import { isObjectOf } from "./object_of.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `Omit, K>`. * + * It only supports modifing a predicate function annotated with `IsPredObj`, usually returned by the followings + * + * - {@linkcode isIntersectionOf} + * - {@linkcode isObjectOf} + * - {@linkcode isOmitOf} + * - {@linkcode isPartialOf} + * - {@linkcode isPickOf} + * - {@linkcode isReadonlyOf} + * - {@linkcode isRequiredOf} + * - {@linkcode isStrictOf} + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript @@ -27,16 +38,16 @@ export function isOmitOf< P extends Record>, K extends keyof T, >( - pred: Predicate & WithPredObj

, + pred: Predicate & IsPredObj

, keys: K[], ): & Predicate>> - & WithPredObj

{ + & IsPredObj

{ const s = new Set(keys); const predObj = Object.fromEntries( Object.entries(pred.predObj).filter(([k]) => !s.has(k as K)), ); return isObjectOf(predObj) as & Predicate>> - & WithPredObj

; + & IsPredObj

; } diff --git a/is/omit_of_test.ts b/is/omit_of_test.ts index d87787e..107d4f2 100644 --- a/is/omit_of_test.ts +++ b/is/omit_of_test.ts @@ -11,24 +11,13 @@ Deno.test("isOmitOf", async (t) => { b: is.String, c: is.Boolean, }); - await t.step("returns properly named function", async (t) => { + + await t.step("returns properly named predicate function", async (t) => { + assertEquals(typeof isOmitOf(pred, ["b"]), "function"); await assertSnapshot(t, isOmitOf(pred, ["b"]).name); - // Nestable await assertSnapshot(t, isOmitOf(isOmitOf(pred, ["b"]), ["c"]).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0, b: "a", c: true }; - if (isOmitOf(pred, ["b"])(a)) { - assertType< - Equal - >(true); - } - if (isOmitOf(isOmitOf(pred, ["b"]), ["c"])(a)) { - assertType< - Equal - >(true); - } - }); + await t.step("returns true on Omit object", () => { assertEquals( isOmitOf(pred, ["b"])({ a: 0, b: undefined, c: true }), @@ -36,6 +25,7 @@ Deno.test("isOmitOf", async (t) => { ); assertEquals(isOmitOf(pred, ["b", "c"])({ a: 0 }), true); }); + await t.step("returns false on non Omit object", () => { assertEquals( isOmitOf(pred, ["b"])("a"), @@ -48,4 +38,20 @@ Deno.test("isOmitOf", async (t) => { "Object have a different type property", ); }); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0, b: "a", c: true }; + + if (isOmitOf(pred, ["b"])(a)) { + assertType< + Equal + >(true); + } + + if (isOmitOf(isOmitOf(pred, ["b"]), ["c"])(a)) { + assertType< + Equal + >(true); + } + }); }); diff --git a/is/parameters_of_test.ts b/is/parameters_of_test.ts index f0dfffa..6bae4b2 100644 --- a/is/parameters_of_test.ts +++ b/is/parameters_of_test.ts @@ -1,13 +1,14 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { as } from "../as/mod.ts"; import { is } from "./mod.ts"; import { isParametersOf } from "./parameters_of.ts"; Deno.test("isParametersOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { + assertEquals(typeof isParametersOf([]), "function"); await assertSnapshot( t, isParametersOf([is.Number, is.String, as.Optional(is.Boolean)]).name, @@ -20,7 +21,6 @@ Deno.test("isParametersOf", async (t) => { t, isParametersOf([]).name, ); - // Nested await assertSnapshot( t, isParametersOf([ @@ -30,7 +30,20 @@ Deno.test("isParametersOf", async (t) => { ]).name, ); }); - await t.step("returns proper type predicate", () => { + + await t.step("returns true on T tuple", () => { + const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; + assertEquals(isParametersOf(predTup)([0, "a", true]), true); + assertEquals(isParametersOf(predTup)([0, "a"]), true); + }); + + await t.step("returns false on non T tuple", () => { + const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; + assertEquals(isParametersOf(predTup)([0, 1, 2]), false); + assertEquals(isParametersOf(predTup)([0, "a", true, 0]), false); + }); + + await t.step("predicated type is correct", () => { const predTup = [ as.Optional(is.Number), is.String, @@ -44,27 +57,11 @@ Deno.test("isParametersOf", async (t) => { >(true); } }); - await t.step("returns true on T tuple", () => { - const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; - assertEquals(isParametersOf(predTup)([0, "a", true]), true); - assertEquals(isParametersOf(predTup)([0, "a"]), true); - }); - await t.step("returns false on non T tuple", () => { - const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; - assertEquals(isParametersOf(predTup)([0, 1, 2]), false); - assertEquals(isParametersOf(predTup)([0, "a", true, 0]), false); - }); - await testWithExamples( - t, - isParametersOf([(_: unknown): _ is unknown => true]), - { - excludeExamples: ["array"], - }, - ); }); Deno.test("isParametersOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { + assertEquals(typeof isParametersOf([], is.Array), "function"); await assertSnapshot( t, isParametersOf([is.Number, is.String, as.Optional(is.Boolean)], is.Array) @@ -75,12 +72,10 @@ Deno.test("isParametersOf", async (t) => { isParametersOf([(_x): _x is string => false], is.ArrayOf(is.String)) .name, ); - // Empty await assertSnapshot( t, isParametersOf([], is.ArrayOf(is.String)).name, ); - // Nested await assertSnapshot( t, isParametersOf([ @@ -94,26 +89,7 @@ Deno.test("isParametersOf", async (t) => { ]).name, ); }); - await t.step("returns proper type predicate", () => { - const predTup = [ - as.Optional(is.Number), - is.String, - as.Optional(is.String), - as.Optional(is.Boolean), - ] as const; - const predElse = is.ArrayOf(is.Number); - const a: unknown = [0, "a"]; - if (isParametersOf(predTup, predElse)(a)) { - assertType< - Equal< - typeof a, - [number | undefined, string, string?, boolean?, ...number[]] - > - >( - true, - ); - } - }); + await t.step("returns true on T tuple", () => { const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; const predElse = is.ArrayOf(is.Number); @@ -127,6 +103,7 @@ Deno.test("isParametersOf", async (t) => { ); assertEquals(isParametersOf(predTup, predElse)([0, "a"]), true); }); + await t.step("returns false on non T tuple", () => { const predTup = [is.Number, is.String, as.Optional(is.Boolean)] as const; const predElse = is.ArrayOf(is.String); @@ -142,12 +119,25 @@ Deno.test("isParametersOf", async (t) => { ); assertEquals(isParametersOf(predTup, predElse)([0, "a", "b"]), false); }); - const predElse = is.Array; - await testWithExamples( - t, - isParametersOf([(_: unknown): _ is unknown => true], predElse), - { - excludeExamples: ["array"], - }, - ); + + await t.step("predicated type is correct", () => { + const predTup = [ + as.Optional(is.Number), + is.String, + as.Optional(is.String), + as.Optional(is.Boolean), + ] as const; + const predElse = is.ArrayOf(is.Number); + const a: unknown = [0, "a"]; + if (isParametersOf(predTup, predElse)(a)) { + assertType< + Equal< + typeof a, + [number | undefined, string, string?, boolean?, ...number[]] + > + >( + true, + ); + } + }); }); diff --git a/is/partial_of.ts b/is/partial_of.ts index 00cd25e..440db32 100644 --- a/is/partial_of.ts +++ b/is/partial_of.ts @@ -1,5 +1,5 @@ import type { FlatType } from "../_typeutil.ts"; -import type { WithPredObj } from "../_annotation.ts"; +import type { IsPredObj } from "../_annotation.ts"; import { asOptional } from "../as/optional.ts"; import type { Predicate } from "../type.ts"; import { isObjectOf } from "./object_of.ts"; @@ -7,6 +7,17 @@ import { isObjectOf } from "./object_of.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `Partial>`. * + * It only supports modifing a predicate function annotated with `IsPredObj`, usually returned by the followings + * + * - {@linkcode isIntersectionOf} + * - {@linkcode isObjectOf} + * - {@linkcode isOmitOf} + * - {@linkcode isPartialOf} + * - {@linkcode isPickOf} + * - {@linkcode isReadonlyOf} + * - {@linkcode isRequiredOf} + * - {@linkcode isStrictOf} + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript @@ -27,14 +38,14 @@ export function isPartialOf< T extends Record, P extends Record>, >( - pred: Predicate & WithPredObj

, + pred: Predicate & IsPredObj

, ): & Predicate>> - & WithPredObj

{ + & IsPredObj

{ const predObj = Object.fromEntries( Object.entries(pred.predObj).map(([k, v]) => [k, asOptional(v)]), ) as Record>; return isObjectOf(predObj) as & Predicate>> - & WithPredObj

; + & IsPredObj

; } diff --git a/is/partial_of_test.ts b/is/partial_of_test.ts index 0de3e26..de0a584 100644 --- a/is/partial_of_test.ts +++ b/is/partial_of_test.ts @@ -13,22 +13,12 @@ Deno.test("isPartialOf", async (t) => { c: as.Optional(is.Boolean), d: as.Readonly(is.String), }); - await t.step("returns properly named function", async (t) => { + + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isPartialOf(pred).name); - // Nestable (no effect) await assertSnapshot(t, isPartialOf(isPartialOf(pred)).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0, b: "a", c: true }; - if (isPartialOf(pred)(a)) { - assertType< - Equal< - typeof a, - Partial<{ a: number; b: string; c: boolean; readonly d: string }> - > - >(true); - } - }); + await t.step("returns true on Partial object", () => { assertEquals( isPartialOf(pred)({ a: undefined, b: undefined, c: undefined }), @@ -36,6 +26,7 @@ Deno.test("isPartialOf", async (t) => { ); assertEquals(isPartialOf(pred)({}), true); }); + await t.step("returns false on non Partial object", () => { assertEquals(isPartialOf(pred)("a"), false, "Value is not an object"); assertEquals( @@ -44,4 +35,16 @@ Deno.test("isPartialOf", async (t) => { "Object have a different type property", ); }); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0, b: "a", c: true }; + if (isPartialOf(pred)(a)) { + assertType< + Equal< + typeof a, + Partial<{ a: number; b: string; c: boolean; readonly d: string }> + > + >(true); + } + }); }); diff --git a/is/pick_of.ts b/is/pick_of.ts index 0a37820..e605ceb 100644 --- a/is/pick_of.ts +++ b/is/pick_of.ts @@ -1,11 +1,22 @@ import type { FlatType } from "../_typeutil.ts"; -import type { WithPredObj } from "../_annotation.ts"; +import type { IsPredObj } from "../_annotation.ts"; import type { Predicate } from "../type.ts"; import { isObjectOf } from "./object_of.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `Pick, K>`. * + * It only supports modifing a predicate function annotated with `IsPredObj`, usually returned by the followings + * + * - {@linkcode isIntersectionOf} + * - {@linkcode isObjectOf} + * - {@linkcode isOmitOf} + * - {@linkcode isPartialOf} + * - {@linkcode isPickOf} + * - {@linkcode isReadonlyOf} + * - {@linkcode isRequiredOf} + * - {@linkcode isStrictOf} + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript @@ -27,16 +38,16 @@ export function isPickOf< P extends Record>, K extends keyof T, >( - pred: Predicate & WithPredObj

, + pred: Predicate & IsPredObj

, keys: K[], ): & Predicate>> - & WithPredObj

{ + & IsPredObj

{ const s = new Set(keys); const predObj = Object.fromEntries( Object.entries(pred.predObj).filter(([k]) => s.has(k as K)), ); return isObjectOf(predObj) as & Predicate>> - & WithPredObj

; + & IsPredObj

; } diff --git a/is/pick_of_test.ts b/is/pick_of_test.ts index 5213e5a..9f79564 100644 --- a/is/pick_of_test.ts +++ b/is/pick_of_test.ts @@ -11,24 +11,12 @@ Deno.test("isPickOf", async (t) => { b: is.String, c: is.Boolean, }); - await t.step("returns properly named function", async (t) => { + + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isPickOf(pred, ["a", "c"]).name); - // Nestable await assertSnapshot(t, isPickOf(isPickOf(pred, ["a", "c"]), ["a"]).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0, b: "a", c: true }; - if (isPickOf(pred, ["a", "c"])(a)) { - assertType< - Equal - >(true); - } - if (isPickOf(isPickOf(pred, ["a", "c"]), ["a"])(a)) { - assertType< - Equal - >(true); - } - }); + await t.step("returns true on Pick object", () => { assertEquals( isPickOf(pred, ["a", "c"])({ a: 0, b: undefined, c: true }), @@ -36,6 +24,7 @@ Deno.test("isPickOf", async (t) => { ); assertEquals(isPickOf(pred, ["a"])({ a: 0 }), true); }); + await t.step("returns false on non Pick object", () => { assertEquals( isPickOf(pred, ["a", "c"])("a"), @@ -48,4 +37,18 @@ Deno.test("isPickOf", async (t) => { "Object have a different type property", ); }); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0, b: "a", c: true }; + if (isPickOf(pred, ["a", "c"])(a)) { + assertType< + Equal + >(true); + } + if (isPickOf(isPickOf(pred, ["a", "c"]), ["a"])(a)) { + assertType< + Equal + >(true); + } + }); }); diff --git a/is/readonly_of.ts b/is/readonly_of.ts index dc798e3..c9e2671 100644 --- a/is/readonly_of.ts +++ b/is/readonly_of.ts @@ -1,5 +1,5 @@ import { rewriteName } from "../_funcutil.ts"; -import type { WithPredObj } from "../_annotation.ts"; +import type { IsPredObj } from "../_annotation.ts"; import type { Predicate } from "../type.ts"; /** @@ -25,10 +25,10 @@ export function isReadonlyOf< T extends Record, P extends Record>, >( - pred: Predicate & WithPredObj

, + pred: Predicate & IsPredObj

, ): & Predicate> - & WithPredObj

; + & IsPredObj

; export function isReadonlyOf< T extends Record, >( diff --git a/is/readonly_of_test.ts b/is/readonly_of_test.ts index 473ab8a..0661542 100644 --- a/is/readonly_of_test.ts +++ b/is/readonly_of_test.ts @@ -9,22 +9,11 @@ import { isReadonlyOf } from "./readonly_of.ts"; Deno.test("isReadonlyOf", async (t) => { await t.step("with isRecord", async (t) => { const pred = is.Record; - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isReadonlyOf(pred).name); - // Nestable (no effect) await assertSnapshot(t, isReadonlyOf(isReadonlyOf(pred)).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0, b: "a", c: true }; - if (isReadonlyOf(pred)(a)) { - assertType< - Equal< - typeof a, - Readonly> - > - >(true); - } - }); + await t.step("returns true on Readonly object", () => { assertEquals( isReadonlyOf(pred)({ a: 0, b: "b", c: true } as const), @@ -35,6 +24,7 @@ Deno.test("isReadonlyOf", async (t) => { true, ); }); + await t.step("returns false on non Readonly object", () => { assertEquals(isReadonlyOf(pred)("a"), false, "Value is not an object"); assertEquals( @@ -43,29 +33,31 @@ Deno.test("isReadonlyOf", async (t) => { "Object have a different type property", ); }); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0, b: "a", c: true }; + if (isReadonlyOf(pred)(a)) { + assertType< + Equal< + typeof a, + Readonly> + > + >(true); + } + }); }); + await t.step("with isObjectOf", async (t) => { const pred = is.ObjectOf({ a: is.Number, b: is.UnionOf([is.String, is.Undefined]), c: as.Readonly(is.Boolean), }); - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isReadonlyOf(pred).name); - // Nestable (no effect) await assertSnapshot(t, isReadonlyOf(isReadonlyOf(pred)).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0, b: "a", c: true }; - if (isReadonlyOf(pred)(a)) { - assertType< - Equal< - typeof a, - Readonly<{ a: number; b: string | undefined; c: boolean }> - > - >(true); - } - }); + await t.step("returns true on Readonly object", () => { assertEquals( isReadonlyOf(pred)({ a: 0, b: "b", c: true } as const), @@ -76,6 +68,7 @@ Deno.test("isReadonlyOf", async (t) => { true, ); }); + await t.step("returns false on non Readonly object", () => { assertEquals(isReadonlyOf(pred)("a"), false, "Value is not an object"); assertEquals( @@ -84,25 +77,27 @@ Deno.test("isReadonlyOf", async (t) => { "Object have a different type property", ); }); - }); - await t.step("with isTupleOf", async (t) => { - const pred = is.TupleOf([is.Number, is.String, as.Readonly(is.Boolean)]); - await t.step("returns properly named function", async (t) => { - await assertSnapshot(t, isReadonlyOf(pred).name); - // Nestable (no effect) - await assertSnapshot(t, isReadonlyOf(isReadonlyOf(pred)).name); - }); - await t.step("returns proper type predicate", () => { - const a: unknown = []; + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0, b: "a", c: true }; if (isReadonlyOf(pred)(a)) { assertType< Equal< typeof a, - Readonly<[number, string, boolean]> + Readonly<{ a: number; b: string | undefined; c: boolean }> > >(true); } }); + }); + + await t.step("with isTupleOf", async (t) => { + const pred = is.TupleOf([is.Number, is.String, as.Readonly(is.Boolean)]); + await t.step("returns properly named predicate function", async (t) => { + await assertSnapshot(t, isReadonlyOf(pred).name); + await assertSnapshot(t, isReadonlyOf(isReadonlyOf(pred)).name); + }); + await t.step("returns true on Readonly object", () => { assertEquals( isReadonlyOf(pred)([0, "b", true] as const), @@ -113,6 +108,7 @@ Deno.test("isReadonlyOf", async (t) => { true, ); }); + await t.step("returns false on non Readonly object", () => { assertEquals(isReadonlyOf(pred)("a"), false, "Value is not an object"); assertEquals( @@ -121,25 +117,27 @@ Deno.test("isReadonlyOf", async (t) => { "Object have a different type property", ); }); - }); - await t.step("with isUniformTupleOf", async (t) => { - const pred = is.UniformTupleOf(3, is.Number); - await t.step("returns properly named function", async (t) => { - await assertSnapshot(t, isReadonlyOf(pred).name); - // Nestable (no effect) - await assertSnapshot(t, isReadonlyOf(isReadonlyOf(pred)).name); - }); - await t.step("returns proper type predicate", () => { + + await t.step("predicated type is correct", () => { const a: unknown = []; if (isReadonlyOf(pred)(a)) { assertType< Equal< typeof a, - Readonly<[number, number, number]> + Readonly<[number, string, boolean]> > >(true); } }); + }); + + await t.step("with isUniformTupleOf", async (t) => { + const pred = is.UniformTupleOf(3, is.Number); + await t.step("returns properly named predicate function", async (t) => { + await assertSnapshot(t, isReadonlyOf(pred).name); + await assertSnapshot(t, isReadonlyOf(isReadonlyOf(pred)).name); + }); + await t.step("returns true on Readonly object", () => { assertEquals( isReadonlyOf(pred)([0, 1, 2] as const), @@ -150,6 +148,7 @@ Deno.test("isReadonlyOf", async (t) => { true, ); }); + await t.step("returns false on non Readonly object", () => { assertEquals(isReadonlyOf(pred)("a"), false, "Value is not an object"); assertEquals( @@ -158,5 +157,17 @@ Deno.test("isReadonlyOf", async (t) => { "Object have a different type property", ); }); + + await t.step("predicated type is correct", () => { + const a: unknown = []; + if (isReadonlyOf(pred)(a)) { + assertType< + Equal< + typeof a, + Readonly<[number, number, number]> + > + >(true); + } + }); }); }); diff --git a/is/record_object_of.ts b/is/record_object_of.ts index a8cd8e3..dbd05f8 100644 --- a/is/record_object_of.ts +++ b/is/record_object_of.ts @@ -5,11 +5,11 @@ import { isRecordObject } from "./record_object.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is an Object instance that satisfies `Record`. * - * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. - * * Note that this function check if the `x` is an instance of `Object`. * Use {@linkcode isRecordOf} instead if you want to check if the `x` satisfies the `Record` type. * + * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/record_object_of_test.ts b/is/record_object_of_test.ts index b209932..596ea05 100644 --- a/is/record_object_of_test.ts +++ b/is/record_object_of_test.ts @@ -1,74 +1,67 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { isRecordObjectOf } from "./record_object_of.ts"; Deno.test("isRecordObjectOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isRecordObjectOf(is.Number).name); await assertSnapshot(t, isRecordObjectOf((_x): _x is string => false).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0 }; - if (isRecordObjectOf(is.Number)(a)) { - assertType>>(true); - } - }); + await t.step("returns true on T record", () => { assertEquals(isRecordObjectOf(is.Number)({ a: 0 }), true); assertEquals(isRecordObjectOf(is.String)({ a: "a" }), true); assertEquals(isRecordObjectOf(is.Boolean)({ a: true }), true); }); + await t.step("returns false on non T record", () => { assertEquals(isRecordObjectOf(is.String)({ a: 0 }), false); assertEquals(isRecordObjectOf(is.Number)({ a: "a" }), false); assertEquals(isRecordObjectOf(is.String)({ a: true }), false); }); - await testWithExamples( - t, - isRecordObjectOf((_: unknown): _ is unknown => true), - { - excludeExamples: ["record"], - }, - ); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0 }; + if (isRecordObjectOf(is.Number)(a)) { + assertType>>(true); + } + }); }); Deno.test("isRecordObjectOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isRecordObjectOf(is.Number, is.String).name); await assertSnapshot( t, isRecordObjectOf((_x): _x is string => false, is.String).name, ); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0 }; - if (isRecordObjectOf(is.Number, is.String)(a)) { - assertType>>(true); - } - }); + await t.step("returns true on T record", () => { assertEquals(isRecordObjectOf(is.Number, is.String)({ a: 0 }), true); assertEquals(isRecordObjectOf(is.String, is.String)({ a: "a" }), true); assertEquals(isRecordObjectOf(is.Boolean, is.String)({ a: true }), true); }); + await t.step("returns false on non T record", () => { assertEquals(isRecordObjectOf(is.String, is.String)({ a: 0 }), false); assertEquals(isRecordObjectOf(is.Number, is.String)({ a: "a" }), false); assertEquals(isRecordObjectOf(is.String, is.String)({ a: true }), false); }); + await t.step("returns false on non K record", () => { assertEquals(isRecordObjectOf(is.Number, is.Number)({ a: 0 }), false); assertEquals(isRecordObjectOf(is.String, is.Number)({ a: "a" }), false); assertEquals(isRecordObjectOf(is.Boolean, is.Number)({ a: true }), false); }); - await testWithExamples( - t, - isRecordObjectOf((_: unknown): _ is unknown => true), - { - excludeExamples: ["record"], - }, - ); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0 }; + if (isRecordObjectOf(is.Number, is.String)(a)) { + assertType>>(true); + } + }); }); diff --git a/is/record_of.ts b/is/record_of.ts index 2d0d3d6..4676f71 100644 --- a/is/record_of.ts +++ b/is/record_of.ts @@ -5,11 +5,11 @@ import { isRecord } from "./record.ts"; /** * Return a type predicate function that returns `true` if the type of `x` satisfies `Record`. * - * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. - * * Note that this function only check if the `x` satisfies the `Record` type. * Use {@linkcode isRecordObjectOf} instead if you want to check if the `x` is an instance of `Object`. * + * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/record_of_test.ts b/is/record_of_test.ts index 3c30c13..91cf7d6 100644 --- a/is/record_of_test.ts +++ b/is/record_of_test.ts @@ -1,74 +1,67 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { isRecordOf } from "./record_of.ts"; Deno.test("isRecordOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isRecordOf(is.Number).name); await assertSnapshot(t, isRecordOf((_x): _x is string => false).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0 }; - if (isRecordOf(is.Number)(a)) { - assertType>>(true); - } - }); + await t.step("returns true on T record", () => { assertEquals(isRecordOf(is.Number)({ a: 0 }), true); assertEquals(isRecordOf(is.String)({ a: "a" }), true); assertEquals(isRecordOf(is.Boolean)({ a: true }), true); }); + await t.step("returns false on non T record", () => { assertEquals(isRecordOf(is.String)({ a: 0 }), false); assertEquals(isRecordOf(is.Number)({ a: "a" }), false); assertEquals(isRecordOf(is.String)({ a: true }), false); }); - await testWithExamples( - t, - isRecordOf((_: unknown): _ is unknown => true), - { - excludeExamples: ["record", "date", "promise", "set", "map"], - }, - ); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0 }; + if (isRecordOf(is.Number)(a)) { + assertType>>(true); + } + }); }); Deno.test("isRecordOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isRecordOf(is.Number, is.String).name); await assertSnapshot( t, isRecordOf((_x): _x is string => false, is.String).name, ); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0 }; - if (isRecordOf(is.Number, is.String)(a)) { - assertType>>(true); - } - }); + await t.step("returns true on T record", () => { assertEquals(isRecordOf(is.Number, is.String)({ a: 0 }), true); assertEquals(isRecordOf(is.String, is.String)({ a: "a" }), true); assertEquals(isRecordOf(is.Boolean, is.String)({ a: true }), true); }); + await t.step("returns false on non T record", () => { assertEquals(isRecordOf(is.String, is.String)({ a: 0 }), false); assertEquals(isRecordOf(is.Number, is.String)({ a: "a" }), false); assertEquals(isRecordOf(is.String, is.String)({ a: true }), false); }); + await t.step("returns false on non K record", () => { assertEquals(isRecordOf(is.Number, is.Number)({ a: 0 }), false); assertEquals(isRecordOf(is.String, is.Number)({ a: "a" }), false); assertEquals(isRecordOf(is.Boolean, is.Number)({ a: true }), false); }); - await testWithExamples( - t, - isRecordOf((_: unknown): _ is unknown => true), - { - excludeExamples: ["record", "date", "promise", "set", "map"], - }, - ); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0 }; + if (isRecordOf(is.Number, is.String)(a)) { + assertType>>(true); + } + }); }); diff --git a/is/required_of.ts b/is/required_of.ts index 33c2a71..3b7fba7 100644 --- a/is/required_of.ts +++ b/is/required_of.ts @@ -1,5 +1,5 @@ import type { FlatType } from "../_typeutil.ts"; -import type { WithPredObj } from "../_annotation.ts"; +import type { IsPredObj } from "../_annotation.ts"; import { asUnoptional } from "../as/optional.ts"; import type { Predicate } from "../type.ts"; import { isObjectOf } from "./object_of.ts"; @@ -7,6 +7,17 @@ import { isObjectOf } from "./object_of.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `Required>`. * + * It only supports modifing a predicate function annotated with `IsPredObj`, usually returned by the followings + * + * - {@linkcode isIntersectionOf} + * - {@linkcode isObjectOf} + * - {@linkcode isOmitOf} + * - {@linkcode isPartialOf} + * - {@linkcode isPickOf} + * - {@linkcode isReadonlyOf} + * - {@linkcode isRequiredOf} + * - {@linkcode isStrictOf} + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript @@ -27,14 +38,14 @@ export function isRequiredOf< T extends Record, P extends Record>, >( - pred: Predicate & WithPredObj

, + pred: Predicate & IsPredObj

, ): & Predicate>> - & WithPredObj

{ + & IsPredObj

{ const predObj = Object.fromEntries( Object.entries(pred.predObj).map(([k, v]) => [k, asUnoptional(v)]), ); return isObjectOf(predObj) as & Predicate>> - & WithPredObj

; + & IsPredObj

; } diff --git a/is/required_of_test.ts b/is/required_of_test.ts index 11e947b..16c00e2 100644 --- a/is/required_of_test.ts +++ b/is/required_of_test.ts @@ -13,22 +13,11 @@ Deno.test("isRequiredOf", async (t) => { c: as.Optional(is.Boolean), d: as.Readonly(is.String), }); - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isRequiredOf(pred).name); - // Nestable (no effect) await assertSnapshot(t, isRequiredOf(isRequiredOf(pred)).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = { a: 0, b: "a", c: true }; - if (isRequiredOf(pred)(a)) { - assertType< - Equal< - typeof a, - { a: number; b: string | undefined; c: boolean; readonly d: string } - > - >(true); - } - }); + await t.step("returns true on Required object", () => { assertEquals( isRequiredOf(pred)({ a: undefined, b: undefined, c: undefined }), @@ -41,6 +30,7 @@ Deno.test("isRequiredOf", async (t) => { "Object does not have required properties", ); }); + await t.step("returns false on non Required object", () => { assertEquals(isRequiredOf(pred)("a"), false, "Value is not an object"); assertEquals( @@ -49,4 +39,16 @@ Deno.test("isRequiredOf", async (t) => { "Object have a different type property", ); }); + + await t.step("predicated type is correct", () => { + const a: unknown = { a: 0, b: "a", c: true }; + if (isRequiredOf(pred)(a)) { + assertType< + Equal< + typeof a, + { a: number; b: string | undefined; c: boolean; readonly d: string } + > + >(true); + } + }); }); diff --git a/is/set.ts b/is/set.ts index e7a3341..fe5a308 100644 --- a/is/set.ts +++ b/is/set.ts @@ -1,6 +1,8 @@ /** * Return `true` if the type of `x` is `Set`. * + * Use {@linkcode isSetOf} to check if the type of `x` is a set of `T`. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/set_of.ts b/is/set_of.ts index 9084f24..0f45ffb 100644 --- a/is/set_of.ts +++ b/is/set_of.ts @@ -5,6 +5,8 @@ import { isSet } from "./set.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `Set`. * + * Use {@linkcode isSet} to check if the type of `x` is a set of `unknown`. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts diff --git a/is/set_of_test.ts b/is/set_of_test.ts index 48aacd1..84498b4 100644 --- a/is/set_of_test.ts +++ b/is/set_of_test.ts @@ -1,32 +1,32 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { isSetOf } from "./set_of.ts"; Deno.test("isSetOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isSetOf(is.Number).name); await assertSnapshot(t, isSetOf((_x): _x is string => false).name); }); - await t.step("returns proper type predicate", () => { - const a: unknown = new Set([0, 1, 2]); - if (isSetOf(is.Number)(a)) { - assertType>>(true); - } - }); + await t.step("returns true on T set", () => { assertEquals(isSetOf(is.Number)(new Set([0, 1, 2])), true); assertEquals(isSetOf(is.String)(new Set(["a", "b", "c"])), true); assertEquals(isSetOf(is.Boolean)(new Set([true, false, true])), true); }); + await t.step("returns false on non T set", () => { assertEquals(isSetOf(is.String)(new Set([0, 1, 2])), false); assertEquals(isSetOf(is.Number)(new Set(["a", "b", "c"])), false); assertEquals(isSetOf(is.String)(new Set([true, false, true])), false); }); - await testWithExamples(t, isSetOf((_: unknown): _ is unknown => true), { - excludeExamples: ["set"], + + await t.step("predicated type is correct", () => { + const a: unknown = new Set([0, 1, 2]); + if (isSetOf(is.Number)(a)) { + assertType>>(true); + } }); }); diff --git a/is/strict_of.ts b/is/strict_of.ts index e091771..0181c2d 100644 --- a/is/strict_of.ts +++ b/is/strict_of.ts @@ -1,10 +1,21 @@ import { rewriteName } from "../_funcutil.ts"; -import type { WithPredObj } from "../_annotation.ts"; +import type { IsPredObj } from "../_annotation.ts"; import type { Predicate } from "../type.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is strictly follow the `ObjectOf`. * + * It only supports modifing a predicate function annotated with `IsPredObj`, usually returned by the followings + * + * - {@linkcode isIntersectionOf} + * - {@linkcode isObjectOf} + * - {@linkcode isOmitOf} + * - {@linkcode isPartialOf} + * - {@linkcode isPickOf} + * - {@linkcode isReadonlyOf} + * - {@linkcode isRequiredOf} + * - {@linkcode isStrictOf} + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts @@ -25,12 +36,10 @@ export function isStrictOf< T extends Record, P extends Record>, >( - pred: - & Predicate - & WithPredObj

, + pred: Predicate & IsPredObj

, ): & Predicate - & WithPredObj

{ + & IsPredObj

{ const s = new Set(Object.keys(pred.predObj)); return rewriteName( (x: unknown): x is T => { @@ -41,5 +50,5 @@ export function isStrictOf< }, "isStrictOf", pred, - ) as Predicate & WithPredObj

; + ) as Predicate & IsPredObj

; } diff --git a/is/strict_of_test.ts b/is/strict_of_test.ts index f542901..2b93f5a 100644 --- a/is/strict_of_test.ts +++ b/is/strict_of_test.ts @@ -1,13 +1,13 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { as } from "../as/mod.ts"; import { is } from "./mod.ts"; import { isStrictOf } from "./strict_of.ts"; Deno.test("isStrictOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot( t, isStrictOf(is.ObjectOf({ a: is.Number, b: is.String, c: is.Boolean })) @@ -17,7 +17,6 @@ Deno.test("isStrictOf", async (t) => { t, isStrictOf(is.ObjectOf({ a: (_x): _x is string => false })).name, ); - // Nested await assertSnapshot( t, isStrictOf( @@ -29,17 +28,7 @@ Deno.test("isStrictOf", async (t) => { ).name, ); }); - await t.step("returns proper type predicate", () => { - const predObj = { - a: is.Number, - b: is.String, - c: is.Boolean, - }; - const a: unknown = { a: 0, b: "a", c: true }; - if (isStrictOf(is.ObjectOf(predObj))(a)) { - assertType>(true); - } - }); + await t.step("returns true on T object", () => { const predObj = { a: is.Number, @@ -51,6 +40,7 @@ Deno.test("isStrictOf", async (t) => { true, ); }); + await t.step("returns false on non T object", () => { const predObj = { a: is.Number, @@ -78,25 +68,20 @@ Deno.test("isStrictOf", async (t) => { "Object have an unknown property", ); }); - await testWithExamples( - t, - isStrictOf(is.ObjectOf({ a: (_: unknown): _ is unknown => false })), - { excludeExamples: ["record"] }, - ); + + await t.step("predicated type is correct", () => { + const predObj = { + a: is.Number, + b: is.String, + c: is.Boolean, + }; + const a: unknown = { a: 0, b: "a", c: true }; + if (isStrictOf(is.ObjectOf(predObj))(a)) { + assertType>(true); + } + }); + await t.step("with optional properties", async (t) => { - await t.step("returns proper type predicate", () => { - const predObj = { - a: is.Number, - b: is.UnionOf([is.String, is.Undefined]), - c: as.Optional(is.Boolean), - }; - const a: unknown = { a: 0, b: "a" }; - if (isStrictOf(is.ObjectOf(predObj))(a)) { - assertType< - Equal - >(true); - } - }); await t.step("returns true on T object", () => { const predObj = { a: is.Number, @@ -118,6 +103,7 @@ Deno.test("isStrictOf", async (t) => { "Object has `undefined` as value of optional property", ); }); + await t.step("returns false on non T object", () => { const predObj = { a: is.Number, @@ -154,5 +140,19 @@ Deno.test("isStrictOf", async (t) => { "Object have the same number of properties but an unknown property exists", ); }); + + await t.step("predicated type is correct", () => { + const predObj = { + a: is.Number, + b: is.UnionOf([is.String, is.Undefined]), + c: as.Optional(is.Boolean), + }; + const a: unknown = { a: 0, b: "a" }; + if (isStrictOf(is.ObjectOf(predObj))(a)) { + assertType< + Equal + >(true); + } + }); }); }); diff --git a/is/tuple_of.ts b/is/tuple_of.ts index 65ff8d5..ac0d2f6 100644 --- a/is/tuple_of.ts +++ b/is/tuple_of.ts @@ -5,6 +5,8 @@ import { isArray } from "./array.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `TupleOf` or `TupleOf`. * + * Use {@linkcode isUniformTupleOf} to check if the type of `x` is a tuple of uniform types. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts diff --git a/is/tuple_of_test.ts b/is/tuple_of_test.ts index 8aabb02..c930390 100644 --- a/is/tuple_of_test.ts +++ b/is/tuple_of_test.ts @@ -1,12 +1,12 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { isTupleOf } from "./tuple_of.ts"; Deno.test("isTupleOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot( t, isTupleOf([is.Number, is.String, is.Boolean]).name, @@ -15,37 +15,36 @@ Deno.test("isTupleOf", async (t) => { t, isTupleOf([(_x): _x is string => false]).name, ); - // Nested await assertSnapshot( t, isTupleOf([isTupleOf([isTupleOf([is.Number, is.String, is.Boolean])])]) .name, ); }); - await t.step("returns proper type predicate", () => { - const predTup = [is.Number, is.String, is.Boolean] as const; - const a: unknown = [0, "a", true]; - if (isTupleOf(predTup)(a)) { - assertType>(true); - } - }); + await t.step("returns true on T tuple", () => { const predTup = [is.Number, is.String, is.Boolean] as const; assertEquals(isTupleOf(predTup)([0, "a", true]), true); }); + await t.step("returns false on non T tuple", () => { const predTup = [is.Number, is.String, is.Boolean] as const; assertEquals(isTupleOf(predTup)([0, 1, 2]), false); assertEquals(isTupleOf(predTup)([0, "a"]), false); assertEquals(isTupleOf(predTup)([0, "a", true, 0]), false); }); - await testWithExamples(t, isTupleOf([(_: unknown): _ is unknown => true]), { - excludeExamples: ["array"], + + await t.step("predicated type is correct", () => { + const predTup = [is.Number, is.String, is.Boolean] as const; + const a: unknown = [0, "a", true]; + if (isTupleOf(predTup)(a)) { + assertType>(true); + } }); }); Deno.test("isTupleOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot( t, isTupleOf([is.Number, is.String, is.Boolean], is.Array).name, @@ -55,7 +54,6 @@ Deno.test("isTupleOf", async (t) => { isTupleOf([(_x): _x is string => false], is.ArrayOf(is.String)) .name, ); - // Nested await assertSnapshot( t, isTupleOf([ @@ -66,21 +64,13 @@ Deno.test("isTupleOf", async (t) => { ]).name, ); }); - await t.step("returns proper type predicate", () => { - const predTup = [is.Number, is.String, is.Boolean] as const; - const predElse = is.ArrayOf(is.Number); - const a: unknown = [0, "a", true, 0, 1, 2]; - if (isTupleOf(predTup, predElse)(a)) { - assertType>( - true, - ); - } - }); + await t.step("returns true on T tuple", () => { const predTup = [is.Number, is.String, is.Boolean] as const; const predElse = is.ArrayOf(is.Number); assertEquals(isTupleOf(predTup, predElse)([0, "a", true, 0, 1, 2]), true); }); + await t.step("returns false on non T tuple", () => { const predTup = [is.Number, is.String, is.Boolean] as const; const predElse = is.ArrayOf(is.String); @@ -92,12 +82,15 @@ Deno.test("isTupleOf", async (t) => { ); assertEquals(isTupleOf(predTup, predElse)([0, "a", true, 0, 1, 2]), false); }); - const predElse = is.Array; - await testWithExamples( - t, - isTupleOf([(_: unknown): _ is unknown => true], predElse), - { - excludeExamples: ["array"], - }, - ); + + await t.step("predicated type is correct", () => { + const predTup = [is.Number, is.String, is.Boolean] as const; + const predElse = is.ArrayOf(is.Number); + const a: unknown = [0, "a", true, 0, 1, 2]; + if (isTupleOf(predTup, predElse)(a)) { + assertType>( + true, + ); + } + }); }); diff --git a/is/uniform_tuple_of.ts b/is/uniform_tuple_of.ts index 7c428a9..d007912 100644 --- a/is/uniform_tuple_of.ts +++ b/is/uniform_tuple_of.ts @@ -5,6 +5,8 @@ import { isArray } from "./array.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `UniformTupleOf`. * + * Use {@linkcode isTupleOf} to check if the type of `x` is a tuple of `T`. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts diff --git a/is/uniform_tuple_of_test.ts b/is/uniform_tuple_of_test.ts index 78ebbb3..3b4574f 100644 --- a/is/uniform_tuple_of_test.ts +++ b/is/uniform_tuple_of_test.ts @@ -1,12 +1,12 @@ import { assertEquals } from "@std/assert"; import { assertSnapshot } from "@std/testing/snapshot"; import { assertType } from "@std/testing/types"; -import { type Equal, testWithExamples } from "../_testutil.ts"; +import type { Equal } from "../_testutil.ts"; import { is } from "./mod.ts"; import { isUniformTupleOf } from "./uniform_tuple_of.ts"; Deno.test("isUniformTupleOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isUniformTupleOf(3).name); await assertSnapshot(t, isUniformTupleOf(3, is.Number).name); await assertSnapshot( @@ -14,7 +14,19 @@ Deno.test("isUniformTupleOf", async (t) => { isUniformTupleOf(3, (_x): _x is string => false).name, ); }); - await t.step("returns proper type predicate", () => { + + await t.step("returns true on mono-typed T tuple", () => { + assertEquals(isUniformTupleOf(3)([0, 1, 2]), true); + assertEquals(isUniformTupleOf(3, is.Number)([0, 1, 2]), true); + }); + + await t.step("returns false on non mono-typed T tuple", () => { + assertEquals(isUniformTupleOf(4)([0, 1, 2]), false); + assertEquals(isUniformTupleOf(4)([0, 1, 2, 3, 4]), false); + assertEquals(isUniformTupleOf(3, is.Number)(["a", "b", "c"]), false); + }); + + await t.step("predicated type is correct", () => { const a: unknown = [0, 1, 2, 3, 4]; if (isUniformTupleOf(5)(a)) { assertType< @@ -28,16 +40,4 @@ Deno.test("isUniformTupleOf", async (t) => { ); } }); - await t.step("returns true on mono-typed T tuple", () => { - assertEquals(isUniformTupleOf(3)([0, 1, 2]), true); - assertEquals(isUniformTupleOf(3, is.Number)([0, 1, 2]), true); - }); - await t.step("returns false on non mono-typed T tuple", () => { - assertEquals(isUniformTupleOf(4)([0, 1, 2]), false); - assertEquals(isUniformTupleOf(4)([0, 1, 2, 3, 4]), false); - assertEquals(isUniformTupleOf(3, is.Number)(["a", "b", "c"]), false); - }); - await testWithExamples(t, isUniformTupleOf(4), { - excludeExamples: ["array"], - }); }); diff --git a/is/union_of.ts b/is/union_of.ts index 907880c..9e898ec 100644 --- a/is/union_of.ts +++ b/is/union_of.ts @@ -5,6 +5,8 @@ import type { Predicate } from "../type.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `UnionOf`. * + * Use {@linkcode isIntersectionOf} to check if the type of `x` is an intersection of `T`. + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts diff --git a/is/union_of_test.ts b/is/union_of_test.ts index e159b78..8d54953 100644 --- a/is/union_of_test.ts +++ b/is/union_of_test.ts @@ -7,17 +7,33 @@ import { is } from "./mod.ts"; import { isUnionOf } from "./union_of.ts"; Deno.test("isUnionOf", async (t) => { - await t.step("returns properly named function", async (t) => { + await t.step("returns properly named predicate function", async (t) => { await assertSnapshot(t, isUnionOf([is.Number, is.String, is.Boolean]).name); }); - await t.step("returns proper type predicate", () => { + + await t.step("returns true on one of T", () => { + const preds = [is.Number, is.String, is.Boolean] as const; + assertEquals(isUnionOf(preds)(0), true); + assertEquals(isUnionOf(preds)("a"), true); + assertEquals(isUnionOf(preds)(true), true); + }); + + await t.step("returns false on non of T", async (t) => { + const preds = [is.Number, is.String, is.Boolean] as const; + await testWithExamples(t, isUnionOf(preds), { + excludeExamples: ["number", "string", "boolean"], + }); + }); + + await t.step("predicated type is correct", () => { const preds = [is.Number, is.String, is.Boolean] as const; const a: unknown = [0, "a", true]; if (isUnionOf(preds)(a)) { assertType>(true); } }); - await t.step("returns proper type predicate (#49)", () => { + + await t.step("predicated type is correct (#49)", () => { const isFoo = is.ObjectOf({ foo: is.String }); const isBar = is.ObjectOf({ foo: is.String, bar: is.Number }); type Foo = PredicateType; @@ -28,16 +44,4 @@ Deno.test("isUnionOf", async (t) => { assertType>(true); } }); - await t.step("returns true on one of T", () => { - const preds = [is.Number, is.String, is.Boolean] as const; - assertEquals(isUnionOf(preds)(0), true); - assertEquals(isUnionOf(preds)("a"), true); - assertEquals(isUnionOf(preds)(true), true); - }); - await t.step("returns false on non of T", async (t) => { - const preds = [is.Number, is.String, is.Boolean] as const; - await testWithExamples(t, isUnionOf(preds), { - excludeExamples: ["number", "string", "boolean"], - }); - }); }); diff --git a/is/unknown.ts b/is/unknown.ts index 9a72915..e5de964 100644 --- a/is/unknown.ts +++ b/is/unknown.ts @@ -1,6 +1,8 @@ /** * Assume `x` is `unknown` and always return `true` regardless of the type of `x`. * + * Use {@linkcode isAny} to assume that the type of `x` is `any`. + * * ```ts * import { is } from "@core/unknownutil"; *