diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml new file mode 100644 index 0000000..c44218f --- /dev/null +++ b/.github/workflows/bench.yml @@ -0,0 +1,30 @@ +name: Benchmark + +env: + DENO_VERSION: 1.x + +on: + push: + tags: + - "v*" + workflow_dispatch: + +jobs: + bench: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: denoland/setup-deno@v1 + with: + deno-version: ${{ env.DENO_VERSION }} + - name: Cache + run: | + deno cache **/*.ts + - name: Test + run: | + deno bench | tee bench.txt + echo '# 🚀 Benchmarks' >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + cat bench.txt | npx strip-ansi-cli >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + timeout-minutes: 10 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 820f4fa..811e825 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,6 +8,7 @@ on: branches: - main pull_request: + workflow_dispatch: jobs: check: @@ -36,6 +37,10 @@ jobs: - uses: denoland/setup-deno@v1 with: deno-version: ${{ env.DENO_VERSION }} + - name: Cache + run: | + deno cache **/*.ts + timeout-minutes: 5 - name: Test run: | deno task test:coverage @@ -48,18 +53,6 @@ jobs: files: ./coverage.lcov token: ${{ secrets.CODECOV_TOKEN }} - bench: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: denoland/setup-deno@v1 - with: - deno-version: ${{ env.DENO_VERSION }} - - name: Test - run: | - deno bench - timeout-minutes: 5 - jsr-publish: runs-on: ubuntu-latest steps: diff --git a/.scripts/bench.ts b/.scripts/bench.ts deleted file mode 100644 index 75235f9..0000000 --- a/.scripts/bench.ts +++ /dev/null @@ -1,435 +0,0 @@ -import { as } from "../as/mod.ts"; -import { is } from "../is/mod.ts"; - -const cs: unknown[] = [ - "Hello world", - 12345, - 67890n, - true, - ["a", 1, true], - ["a", "b", "c"], - new Set(["a", "b", "c"]), - { a: "a", b: "b", c: "c" }, - { a: "a", b: 1, c: true }, - new Map([["a", 1], ["b", 2], ["c", 3]]), - () => {}, - new Date(), - null, - undefined, - Symbol("a"), -]; - -Deno.bench({ - name: "Warm-up", - fn: () => {}, -}); - -Deno.bench({ - name: "is.Any", - fn: () => { - for (const c of cs) { - is.Any(c); - } - }, -}); - -Deno.bench({ - name: "is.Unknown", - fn: () => { - for (const c of cs) { - is.Unknown(c); - } - }, -}); - -Deno.bench({ - name: "is.String", - fn: () => { - for (const c of cs) { - is.String(c); - } - }, -}); - -Deno.bench({ - name: "is.Number", - fn: () => { - for (const c of cs) { - is.Number(c); - } - }, -}); - -Deno.bench({ - name: "is.Bigint", - fn: () => { - for (const c of cs) { - is.Bigint(c); - } - }, -}); - -Deno.bench({ - name: "is.Boolean", - fn: () => { - for (const c of cs) { - is.Boolean(c); - } - }, -}); - -Deno.bench({ - name: "is.Array", - fn: () => { - for (const c of cs) { - is.Array(c); - } - }, -}); - -Deno.bench({ - name: "is.ArrayOf", - fn: () => { - const pred = is.ArrayOf(is.String); - for (const c of cs) { - pred(c); - } - }, -}); - -const isArrayOfPred = is.ArrayOf(is.String); -Deno.bench({ - name: "is.ArrayOf (pre)", - fn: () => { - for (const c of cs) { - isArrayOfPred(c); - } - }, -}); - -Deno.bench({ - name: "is.Set", - fn: () => { - for (const c of cs) { - is.Set(c); - } - }, -}); - -Deno.bench({ - name: "is.SetOf", - fn: () => { - const pred = is.SetOf(is.String); - for (const c of cs) { - pred(c); - } - }, -}); - -const isSetOfPred = is.SetOf(is.String); -Deno.bench({ - name: "is.SetOf (pre)", - fn: () => { - for (const c of cs) { - isSetOfPred(c); - } - }, -}); - -const predTup = [is.String, is.Number, is.Boolean] as const; -Deno.bench({ - name: "is.TupleOf", - fn: () => { - const pred = is.TupleOf(predTup); - for (const c of cs) { - pred(c); - } - }, -}); - -const isTupleOfPred = is.TupleOf(predTup); -Deno.bench({ - name: "is.TupleOf (pre)", - fn: () => { - for (const c of cs) { - isTupleOfPred(c); - } - }, -}); - -Deno.bench({ - name: "is.TupleOf", - fn: () => { - const pred = is.TupleOf(predTup, is.Array); - for (const c of cs) { - pred(c); - } - }, -}); - -const isTupleOfElsePred = is.TupleOf(predTup, is.Array); -Deno.bench({ - name: "is.TupleOf (pre)", - fn: () => { - for (const c of cs) { - isTupleOfElsePred(c); - } - }, -}); - -Deno.bench({ - name: "is.UniformTupleOf", - fn: () => { - const pred = is.UniformTupleOf(3, is.String); - for (const c of cs) { - pred(c); - } - }, -}); - -const isUniformTupleOfPred = is.UniformTupleOf(3, is.String); -Deno.bench({ - name: "is.UniformTupleOf (pre)", - fn: () => { - for (const c of cs) { - isUniformTupleOfPred(c); - } - }, -}); - -Deno.bench({ - name: "is.Record", - fn: () => { - for (const c of cs) { - is.Record(c); - } - }, -}); - -Deno.bench({ - name: "is.RecordOf", - fn: () => { - const pred = is.RecordOf(is.String); - for (const c of cs) { - pred(c); - } - }, -}); - -const isRecordOfPred = is.RecordOf(is.String); -Deno.bench({ - name: "is.RecordOf (pre)", - fn: () => { - for (const c of cs) { - isRecordOfPred(c); - } - }, -}); - -Deno.bench({ - name: "is.Map", - fn: () => { - for (const c of cs) { - is.Map(c); - } - }, -}); - -Deno.bench({ - name: "is.MapOf", - fn: () => { - const pred = is.MapOf(is.String); - for (const c of cs) { - pred(c); - } - }, -}); - -const isMapOfPred = is.MapOf(is.String); -Deno.bench({ - name: "is.MapOf (pre)", - fn: () => { - for (const c of cs) { - isMapOfPred(c); - } - }, -}); - -const predObj = { - a: is.String, - b: is.Number, - c: is.Boolean, -} as const; -Deno.bench({ - name: "is.ObjectOf", - fn: () => { - const pred = is.ObjectOf(predObj); - for (const c of cs) { - pred(c); - } - }, -}); - -const isObjectOfPred = is.ObjectOf(predObj); -Deno.bench({ - name: "is.ObjectOf (pre)", - fn: () => { - for (const c of cs) { - isObjectOfPred(c); - } - }, -}); - -Deno.bench({ - name: "is.Function", - fn: () => { - for (const c of cs) { - is.Function(c); - } - }, -}); - -Deno.bench({ - name: "is.SyncFunction", - fn: () => { - for (const c of cs) { - is.SyncFunction(c); - } - }, -}); - -Deno.bench({ - name: "is.AsyncFunction", - fn: () => { - for (const c of cs) { - is.AsyncFunction(c); - } - }, -}); - -Deno.bench({ - name: "is.InstanceOf", - fn: () => { - const pred = is.InstanceOf(Date); - for (const c of cs) { - pred(c); - } - }, -}); - -const isInstanceOfPred = is.InstanceOf(Date); -Deno.bench({ - name: "is.InstanceOf (pre)", - fn: () => { - for (const c of cs) { - isInstanceOfPred(c); - } - }, -}); - -Deno.bench({ - name: "is.Null", - fn: () => { - for (const c of cs) { - is.Null(c); - } - }, -}); - -Deno.bench({ - name: "is.Undefined", - fn: () => { - for (const c of cs) { - is.Undefined(c); - } - }, -}); - -Deno.bench({ - name: "is.Nullish", - fn: () => { - for (const c of cs) { - is.Nullish(c); - } - }, -}); - -Deno.bench({ - name: "is.Symbol", - fn: () => { - for (const c of cs) { - is.Symbol(c); - } - }, -}); - -Deno.bench({ - name: "is.Primitive", - fn: () => { - for (const c of cs) { - is.Primitive(c); - } - }, -}); - -const predLiteral = "hello"; -Deno.bench({ - name: "is.LiteralOf", - fn: () => { - const pred = is.LiteralOf(predLiteral); - for (const c of cs) { - pred(c); - } - }, -}); - -const isLiteralOfPred = is.LiteralOf(predLiteral); -Deno.bench({ - name: "is.LiteralOf (pre)", - fn: () => { - for (const c of cs) { - isLiteralOfPred(c); - } - }, -}); - -const predLiteralOne = ["hello", "world"] as const; -Deno.bench({ - name: "is.LiteralOneOf", - fn: () => { - const pred = is.LiteralOneOf(predLiteralOne); - for (const c of cs) { - pred(c); - } - }, -}); - -const isLiteralOneOfPred = is.LiteralOneOf(predLiteralOne); -Deno.bench({ - name: "is.LiteralOneOf (pre)", - fn: () => { - for (const c of cs) { - isLiteralOneOfPred(c); - } - }, -}); - -Deno.bench({ - name: "as.Optional", - fn: () => { - const pred = as.Optional(is.String); - for (const c of cs) { - pred(c); - } - }, -}); - -const asOptionalPred = as.Optional(is.String); -Deno.bench({ - name: "as.Optional (pre)", - fn: () => { - for (const c of cs) { - asOptionalPred(c); - } - }, -}); diff --git a/as/mod.ts b/as/mod.ts index 56fab8f..cc78ac7 100644 --- a/as/mod.ts +++ b/as/mod.ts @@ -14,7 +14,7 @@ export const as: { /** * Annotate the given predicate function as optional. * - * Use this function to annotate a predicate function of `predObj` in {@linkcode isObjectOf}. + * Use this function to annotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}. * * Note that the annotated predicate function will return `true` if the type of `x` is `T` or `undefined`, indicating that * this function is not just for annotation but it also changes the behavior of the predicate function. @@ -40,7 +40,7 @@ export const as: { /** * Annotate the given predicate function as readonly. * - * Use this function to annotate a predicate function of `predObj` in {@linkcode isObjectOf}. + * Use this function to annotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}. * * Use {@linkcode asUnreadonly} to remove the annotation. * Use {@linkcode hasReadonly} to check if a predicate function has annotated with this function. @@ -63,7 +63,7 @@ export const as: { /** * Unannotate the annotated predicate function with {@linkcode asOptional}. * - * Use this function to unannotate a predicate function of `predObj` in {@linkcode isObjectOf}. + * Use this function to unannotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}. * * Note that the annotated predicate function will return `true` if the type of `x` is `T`, indicating that * this function is not just for annotation but it also changes the behavior of the predicate function. @@ -86,7 +86,7 @@ export const as: { /** * Unannotate the annotated predicate function with {@linkcode asReadonly}. * - * Use this function to unannotate a predicate function of `predObj` in {@linkcode isObjectOf}. + * Use this function to unannotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/as/mod_test.ts b/as/mod_test.ts index b93e4aa..b620528 100644 --- a/as/mod_test.ts +++ b/as/mod_test.ts @@ -4,6 +4,8 @@ import { as } from "./mod.ts"; const excludes = [ "mod.ts", + "_*.ts", + "*_bench.ts", "*_test.ts", ]; diff --git a/as/optional.ts b/as/optional.ts index acadffd..53ea462 100644 --- a/as/optional.ts +++ b/as/optional.ts @@ -10,7 +10,7 @@ import { /** * Annotate the given predicate function as optional. * - * Use this function to annotate a predicate function of `predObj` in {@linkcode isObjectOf}. + * Use this function to annotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}. * * Note that the annotated predicate function will return `true` if the type of `x` is `T` or `undefined`, indicating that * this function is not just for annotation but it also changes the behavior of the predicate function. @@ -61,7 +61,7 @@ export function asOptional

>( /** * Unannotate the annotated predicate function with {@linkcode asOptional}. * - * Use this function to unannotate a predicate function of `predObj` in {@linkcode isObjectOf}. + * Use this function to unannotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}. * * Note that the annotated predicate function will return `true` if the type of `x` is `T`, indicating that * this function is not just for annotation but it also changes the behavior of the predicate function. diff --git a/as/optional_bench.ts b/as/optional_bench.ts new file mode 100644 index 0000000..d65f1cd --- /dev/null +++ b/as/optional_bench.ts @@ -0,0 +1,107 @@ +import { + asOptional as asOptional420, + asUnoptional as asUnoptional420, + hasOptional as hasOptional420, +} from "jsr:@core/unknownutil@4.2.0/as/optional"; +import { asOptional, asUnoptional, hasOptional } from "./optional.ts"; + +const repeats = Array.from({ length: 100 }); + +const predicate = (x: unknown): x is string => typeof x === "string"; +const optional = asOptional((x: unknown): x is string => typeof x === "string"); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => asOptional(predicate)); + }, + group: "asOptional (predicate)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => asOptional(optional)); + }, + group: "asOptional (optional)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => asUnoptional(predicate)); + }, + group: "asUnoptional (predicate)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => asUnoptional(optional)); + }, + group: "asUnoptional (optional)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => hasOptional(predicate)); + }, + group: "hasOptional (predicate)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => hasOptional(optional)); + }, + group: "hasOptional (optional)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => asOptional420(predicate)); + }, + group: "asOptional (predicate)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => asOptional420(optional)); + }, + group: "asOptional (optional)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => asUnoptional420(predicate)); + }, + group: "asUnoptional (predicate)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => asUnoptional420(optional)); + }, + group: "asUnoptional (optional)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => hasOptional420(predicate)); + }, + group: "hasOptional (predicate)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => hasOptional420(optional)); + }, + group: "hasOptional (optional)", +}); diff --git a/as/readonly.ts b/as/readonly.ts index ea0293f..b8bf675 100644 --- a/as/readonly.ts +++ b/as/readonly.ts @@ -10,7 +10,7 @@ import { /** * Annotate the given predicate function as readonly. * - * Use this function to annotate a predicate function of `predObj` in {@linkcode isObjectOf}. + * Use this function to annotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}. * * Use {@linkcode asUnreadonly} to remove the annotation. * Use {@linkcode hasReadonly} to check if a predicate function has annotated with this function. @@ -45,7 +45,7 @@ export function asReadonly

>( /** * Unannotate the annotated predicate function with {@linkcode asReadonly}. * - * Use this function to unannotate a predicate function of `predObj` in {@linkcode isObjectOf}. + * Use this function to unannotate a predicate function of `predObj` in {@linkcode [is/object-of].isObjectOf|isObjectOf}. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/as/readonly_bench.ts b/as/readonly_bench.ts new file mode 100644 index 0000000..17b9fa3 --- /dev/null +++ b/as/readonly_bench.ts @@ -0,0 +1,107 @@ +import { + asReadonly as asReadonly420, + asUnreadonly as asUnreadonly420, + hasReadonly as hasReadonly420, +} from "jsr:@core/unknownutil@4.2.0/as/readonly"; +import { asReadonly, asUnreadonly, hasReadonly } from "./readonly.ts"; + +const repeats = Array.from({ length: 100 }); + +const predicate = (x: unknown): x is string => typeof x === "string"; +const readonly = asReadonly((x: unknown): x is string => typeof x === "string"); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => asReadonly(predicate)); + }, + group: "asReadonly (predicate)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => asReadonly(readonly)); + }, + group: "asReadonly (readonly)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => asUnreadonly(predicate)); + }, + group: "asUnreadonly (predicate)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => asUnreadonly(readonly)); + }, + group: "asUnreadonly (readonly)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => hasReadonly(predicate)); + }, + group: "hasReadonly (predicate)", +}); + +Deno.bench({ + name: "current", + fn() { + repeats.forEach(() => hasReadonly(readonly)); + }, + group: "hasReadonly (readonly)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => asReadonly420(predicate)); + }, + group: "asReadonly (predicate)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => asReadonly420(readonly)); + }, + group: "asReadonly (readonly)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => asUnreadonly420(predicate)); + }, + group: "asUnreadonly (predicate)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => asUnreadonly420(readonly)); + }, + group: "asUnreadonly (readonly)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => hasReadonly420(predicate)); + }, + group: "hasReadonly (predicate)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + repeats.forEach(() => hasReadonly420(readonly)); + }, + group: "hasReadonly (readonly)", +}); diff --git a/ensure.ts b/ensure.ts index 8587c03..6de3e7a 100644 --- a/ensure.ts +++ b/ensure.ts @@ -4,7 +4,7 @@ import { assert } from "./assert.ts"; /** * Ensures that the given value satisfies the provided predicate. * - * It throws {@linkcode AssertError} if the value does not satisfy the predicate. + * It throws {@linkcode [assert].AssertError|AssertError} if the value does not satisfy the predicate. * * ```ts * import { ensure, is } from "@core/unknownutil"; diff --git a/is/any.ts b/is/any.ts index e3a177a..f2ffc8a 100644 --- a/is/any.ts +++ b/is/any.ts @@ -1,7 +1,7 @@ /** * Assume `x is `any` and always return `true` regardless of the type of `x`. * - * Use {@linkcode isUnknown} to assume that a value is `unknown`. + * Use {@linkcode [is/unknown].isUnknown|isUnknown} to assume that a value is `unknown`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/any_bench.ts b/is/any_bench.ts new file mode 100644 index 0000000..6bf04c2 --- /dev/null +++ b/is/any_bench.ts @@ -0,0 +1,22 @@ +import { assert } from "@std/assert"; +import { isAny as isAny420 } from "jsr:@core/unknownutil@4.2.0/is/any"; +import { isAny } from "./any.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = ""; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isAny(positive))); + }, + group: "isAny (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isAny420(positive))); + }, + group: "isAny (positive)", +}); diff --git a/is/array.ts b/is/array.ts index 9921c1d..dddaa6a 100644 --- a/is/array.ts +++ b/is/array.ts @@ -1,7 +1,7 @@ /** * Return `true` if the type of `x` is `unknown[]`. * - * Use {@linkcode isArrayOf} to check if the type of `x` is an array of `T`. + * Use {@linkcode [is/arrayt-of].isArrayOf|isArrayOf} to check if the type of `x` is an array of `T`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/array_bench.ts b/is/array_bench.ts new file mode 100644 index 0000000..5805b40 --- /dev/null +++ b/is/array_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isArray as isArray420 } from "jsr:@core/unknownutil@4.2.0/is/array"; +import { isArray } from "./array.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = []; +const negative: unknown = ""; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isArray(positive))); + }, + group: "isArray (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isArray(negative))); + }, + group: "isArray (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isArray420(positive))); + }, + group: "isArray (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isArray420(negative))); + }, + group: "isArray (negative)", +}); diff --git a/is/array_of.ts b/is/array_of.ts index abd4993..8a6a299 100644 --- a/is/array_of.ts +++ b/is/array_of.ts @@ -5,7 +5,7 @@ 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`. + * Use {@linkcode [is/array].isArray|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. * diff --git a/is/array_of_bench.ts b/is/array_of_bench.ts new file mode 100644 index 0000000..9d8293e --- /dev/null +++ b/is/array_of_bench.ts @@ -0,0 +1,112 @@ +import { assert } from "@std/assert"; +import { isArrayOf as isArrayOf420 } from "jsr:@core/unknownutil@4.2.0/is/array-of"; +import { isArrayOf } from "./array_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = []; +const positive10: unknown = Array.from({ length: 10 }).map(() => ""); +const positive1000: unknown = Array.from({ length: 1000 }).map(() => ""); +const negative: unknown = ""; +const negative10: unknown = Array.from({ length: 10 }).map(() => 0); +const negative1000: unknown = Array.from({ length: 1000 }).map(() => 0); + +const pred420 = isArrayOf420((x: unknown): x is string => + typeof x === "string" +); +const pred = isArrayOf((x: unknown): x is string => typeof x === "string"); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isArrayOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isArrayOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isArrayOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isArrayOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isArrayOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isArrayOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isArrayOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isArrayOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isArrayOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isArrayOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isArrayOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isArrayOf (negative 1000)", +}); diff --git a/is/async_function.ts b/is/async_function.ts index 78db3eb..4eedee1 100644 --- a/is/async_function.ts +++ b/is/async_function.ts @@ -3,8 +3,8 @@ 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. + * Use {@linkcode [is/function].isFunction|isFunction} to check if the type of `x` is a function. + * Use {@linkcode [is/sync-function].isSyncFunction|isSyncFunction} to check if the type of `x` is a synchronous function. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/async_function_bench.ts b/is/async_function_bench.ts new file mode 100644 index 0000000..593747c --- /dev/null +++ b/is/async_function_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isAsyncFunction as isAsyncFunction420 } from "jsr:@core/unknownutil@4.2.0/is/async-function"; +import { isAsyncFunction } from "./async_function.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = async () => {}; +const negative: unknown = () => {}; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isAsyncFunction(positive))); + }, + group: "isAsyncFunction (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isAsyncFunction(negative))); + }, + group: "isAsyncFunction (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isAsyncFunction420(positive))); + }, + group: "isAsyncFunction (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isAsyncFunction420(negative))); + }, + group: "isAsyncFunction (negative)", +}); diff --git a/is/bigint_bench.ts b/is/bigint_bench.ts new file mode 100644 index 0000000..854dc2a --- /dev/null +++ b/is/bigint_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isBigint as isBigint420 } from "jsr:@core/unknownutil@4.2.0/is/bigint"; +import { isBigint } from "./bigint.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = 0n; +const negative: unknown = 0; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isBigint(positive))); + }, + group: "isBigint (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isBigint(negative))); + }, + group: "isBigint (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isBigint420(positive))); + }, + group: "isBigint (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isBigint420(negative))); + }, + group: "isBigint (negative)", +}); diff --git a/is/boolean_bench.ts b/is/boolean_bench.ts new file mode 100644 index 0000000..46f090f --- /dev/null +++ b/is/boolean_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isBoolean as isBoolean420 } from "jsr:@core/unknownutil@4.2.0/is/boolean"; +import { isBoolean } from "./boolean.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = true; +const negative: unknown = 0; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isBoolean(positive))); + }, + group: "isBoolean (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isBoolean(negative))); + }, + group: "isBoolean (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isBoolean420(positive))); + }, + group: "isBoolean (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isBoolean420(negative))); + }, + group: "isBoolean (negative)", +}); diff --git a/is/function.ts b/is/function.ts index 9b6cc71..566e9a7 100644 --- a/is/function.ts +++ b/is/function.ts @@ -1,8 +1,8 @@ /** * 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. + * Use {@linkcode [is/sync-function].isSyncFunction|isSyncFunction} to check if the type of `x` is a synchronous function. + * Use {@linkcode [is/async-function].isAsyncFunction|isAsyncFunction} to check if the type of `x` is an asynchronous function. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/function_bench.ts b/is/function_bench.ts new file mode 100644 index 0000000..4a2f183 --- /dev/null +++ b/is/function_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isFunction as isFunction420 } from "jsr:@core/unknownutil@4.2.0/is/function"; +import { isFunction } from "./function.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = () => {}; +const negative: unknown = 0; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isFunction(positive))); + }, + group: "isFunction (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isFunction(negative))); + }, + group: "isFunction (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isFunction420(positive))); + }, + group: "isFunction (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isFunction420(negative))); + }, + group: "isFunction (negative)", +}); diff --git a/is/instance_of_bench.ts b/is/instance_of_bench.ts new file mode 100644 index 0000000..9c8b1f0 --- /dev/null +++ b/is/instance_of_bench.ts @@ -0,0 +1,42 @@ +import { assert } from "@std/assert"; +import { isInstanceOf as isInstanceOf420 } from "jsr:@core/unknownutil@4.2.0/is/instance-of"; +import { isInstanceOf } from "./instance_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = Promise.resolve(); +const negative: unknown = ""; + +const pred420 = isInstanceOf420(Promise); +const pred = isInstanceOf(Promise); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isInstanceOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isInstanceOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isInstanceOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isInstanceOf (negative)", +}); diff --git a/is/intersection_of.ts b/is/intersection_of.ts index 0b748d8..de46010 100644 --- a/is/intersection_of.ts +++ b/is/intersection_of.ts @@ -6,7 +6,7 @@ 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`. + * Use {@linkcode [is/union-of].isUnionOf|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. * diff --git a/is/intersection_of_bench.ts b/is/intersection_of_bench.ts new file mode 100644 index 0000000..3b96fc2 --- /dev/null +++ b/is/intersection_of_bench.ts @@ -0,0 +1,130 @@ +import { assert } from "@std/assert"; +import { isObjectOf } from "./object_of.ts"; +import { isIntersectionOf as isIntersectionOf420 } from "jsr:@core/unknownutil@4.2.0/is/intersection-of"; +import { isIntersectionOf } from "./intersection_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "", b: 0, c: true }; +const positive10: unknown = Object.assign( + { a: "", b: 0, c: true }, + Array.from({ length: 10 }), +); +const positive1000: unknown = Object.assign( + { a: "", b: 0, c: true }, + Array.from({ length: 1000 }), +); +const negative: unknown = {}; +const negative10: unknown = Object.assign({}, Array.from({ length: 10 })); +const negative1000: unknown = Object.assign({}, Array.from({ length: 1000 })); + +const preds = [ + isObjectOf({ + a: (x: unknown): x is string => typeof x === "string", + }), + isObjectOf({ + b: (x: unknown): x is number => typeof x === "number", + }), + isObjectOf({ + c: (x: unknown): x is boolean => typeof x === "boolean", + }), + // deno-lint-ignore ban-types + (x: unknown): x is {} => typeof x === "object", +] as const; +const pred420 = isIntersectionOf420(preds); +const pred = isIntersectionOf(preds); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isIntersectionOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isIntersectionOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isIntersectionOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isIntersectionOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isIntersectionOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isIntersectionOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isIntersectionOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isIntersectionOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isIntersectionOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isIntersectionOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isIntersectionOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isIntersectionOf (negative 1000)", +}); diff --git a/is/literal_of.ts b/is/literal_of.ts index 1388675..ae3fbec 100644 --- a/is/literal_of.ts +++ b/is/literal_of.ts @@ -4,8 +4,8 @@ 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[]`. + * Use {@linkcode [is/literal].isLiteral|isLiteral} to check if the type of `x` is a literal type. + * Use {@linkcode [is/literal-one-of].isLiteralOneOf|isLiteralOneOf} to check if the type of `x` is one of the literal type of {@linkcode [type].Primitive|Primitive[]}. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/is/literal_of_bench.ts b/is/literal_of_bench.ts new file mode 100644 index 0000000..36797e5 --- /dev/null +++ b/is/literal_of_bench.ts @@ -0,0 +1,42 @@ +import { assert } from "@std/assert"; +import { isLiteralOf as isLiteralOf420 } from "jsr:@core/unknownutil@4.2.0/is/literal-of"; +import { isLiteralOf } from "./literal_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = "hello"; +const negative: unknown = "world"; + +const pred420 = isLiteralOf420("hello"); +const pred = isLiteralOf("hello"); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isLiteralOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isLiteralOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isLiteralOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isLiteralOf (negative)", +}); diff --git a/is/literal_one_of.ts b/is/literal_one_of.ts index b60547b..42bb0f2 100644 --- a/is/literal_one_of.ts +++ b/is/literal_one_of.ts @@ -4,8 +4,8 @@ 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`. + * Use {@linkcode [is/literal].isLiteral|isLiteral} to check if the type of `x` is a literal type. + * Use {@linkcode [is/literal-of].isLiteralOf|isLiteralOf} to check if the type of `x` is a literal type of {@linkcode [type].Primitive|Primitive}. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/is/literal_one_of_bench.ts b/is/literal_one_of_bench.ts new file mode 100644 index 0000000..e521bd6 --- /dev/null +++ b/is/literal_one_of_bench.ts @@ -0,0 +1,42 @@ +import { assert } from "@std/assert"; +import { isLiteralOneOf as isLiteralOneOf420 } from "jsr:@core/unknownutil@4.2.0/is/literal-one-of"; +import { isLiteralOneOf } from "./literal_one_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = "hello"; +const negative: unknown = "goodbye"; + +const pred420 = isLiteralOneOf420(["hello", "world"] as const); +const pred = isLiteralOneOf(["hello", "world"] as const); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isLiteralOneOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isLiteralOneOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isLiteralOneOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isLiteralOneOf (negative)", +}); diff --git a/is/map.ts b/is/map.ts index 545a993..ae6aac0 100644 --- a/is/map.ts +++ b/is/map.ts @@ -1,7 +1,7 @@ /** * Return `true` if the type of `x` is `Map`. * - * Use {@linkcode isMapOf} to check if the type of `x` is a map of `T`. + * Use {@linkcode [is/map-of].isMapOf|isMapOf} to check if the type of `x` is a map of `T`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/map_bench.ts b/is/map_bench.ts new file mode 100644 index 0000000..03bbc92 --- /dev/null +++ b/is/map_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isMap as isMap420 } from "jsr:@core/unknownutil@4.2.0/is/map"; +import { isMap } from "./map.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = new Map(); +const negative: unknown = {}; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isMap(positive))); + }, + group: "isMap (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isMap(negative))); + }, + group: "isMap (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isMap420(positive))); + }, + group: "isMap (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isMap420(negative))); + }, + group: "isMap (negative)", +}); diff --git a/is/map_of.ts b/is/map_of.ts index cf4bc68..2065048 100644 --- a/is/map_of.ts +++ b/is/map_of.ts @@ -5,7 +5,7 @@ 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`. + * Use {@linkcode [is/map].isMap|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. * diff --git a/is/map_of_bench.ts b/is/map_of_bench.ts new file mode 100644 index 0000000..3aa67ef --- /dev/null +++ b/is/map_of_bench.ts @@ -0,0 +1,222 @@ +import { assert } from "@std/assert"; +import { isMapOf as isMapOf420 } from "jsr:@core/unknownutil@4.2.0/is/map-of"; +import { isMapOf } from "./map_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = new Map(); +const positive10: unknown = new Map( + Array.from({ length: 10 }).map((_, i) => [i.toString(), ""]), +); +const positive1000: unknown = new Map( + Array.from({ length: 1000 }).map((_, i) => [i.toString(), ""]), +); +const negative: unknown = new Map([["", 0]]); +const negative10: unknown = new Map( + Array.from({ length: 10 }).map((_, i) => [i.toString(), 0]), +); +const negative1000: unknown = new Map( + Array.from({ length: 1000 }).map((_, i) => [i.toString(), 0]), +); + +const pred1420 = isMapOf420((x: unknown): x is string => typeof x === "string"); +const pred2420 = isMapOf420( + (x: unknown): x is string => typeof x === "string", + (x: unknown): x is string => typeof x === "string", +); +const pred1 = isMapOf((x: unknown): x is string => typeof x === "string"); +const pred2 = isMapOf( + (x: unknown): x is string => typeof x === "string", + (x: unknown): x is string => typeof x === "string", +); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive))); + }, + group: "isMapOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive10))); + }, + group: "isMapOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive1000))); + }, + group: "isMapOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative))); + }, + group: "isMapOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative10))); + }, + group: "isMapOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative1000))); + }, + group: "isMapOf (negative 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive))); + }, + group: "isMapOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive10))); + }, + group: "isMapOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive1000))); + }, + group: "isMapOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative))); + }, + group: "isMapOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative10))); + }, + group: "isMapOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative1000))); + }, + group: "isMapOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive))); + }, + group: "isMapOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive10))); + }, + group: "isMapOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive1000))); + }, + group: "isMapOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative))); + }, + group: "isMapOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative10))); + }, + group: "isMapOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative1000))); + }, + group: "isMapOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive))); + }, + group: "isMapOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive10))); + }, + group: "isMapOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive1000))); + }, + group: "isMapOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative))); + }, + group: "isMapOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative10))); + }, + group: "isMapOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative1000))); + }, + group: "isMapOf (negative 1000)", +}); diff --git a/is/mod.ts b/is/mod.ts index 3d1b896..6e6231c 100644 --- a/is/mod.ts +++ b/is/mod.ts @@ -86,7 +86,7 @@ export const is: { /** * Assume `x is `any` and always return `true` regardless of the type of `x`. * - * Use {@linkcode isUnknown} to assume that a value is `unknown`. + * Use {@linkcode [is/unknown].isUnknown|isUnknown} to assume that a value is `unknown`. * * ```ts * import { is } from "@core/unknownutil"; @@ -101,7 +101,7 @@ export const is: { /** * Return `true` if the type of `x` is `unknown[]`. * - * Use {@linkcode isArrayOf} to check if the type of `x` is an array of `T`. + * Use {@linkcode [is/arrayt-of].isArrayOf|isArrayOf} to check if the type of `x` is an array of `T`. * * ```ts * import { is } from "@core/unknownutil"; @@ -116,7 +116,7 @@ export const is: { /** * 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`. + * Use {@linkcode [is/array].isArray|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. * @@ -134,8 +134,8 @@ export const is: { /** * 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. + * Use {@linkcode [is/function].isFunction|isFunction} to check if the type of `x` is a function. + * Use {@linkcode [is/sync-function].isSyncFunction|isSyncFunction} to check if the type of `x` is a synchronous function. * * ```ts * import { is } from "@core/unknownutil"; @@ -176,8 +176,8 @@ export const is: { /** * 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. + * Use {@linkcode [is/sync-function].isSyncFunction|isSyncFunction} to check if the type of `x` is a synchronous function. + * Use {@linkcode [is/async-function].isAsyncFunction|isAsyncFunction} to check if the type of `x` is an asynchronous function. * * ```ts * import { is } from "@core/unknownutil"; @@ -208,7 +208,7 @@ export const is: { /** * 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`. + * Use {@linkcode [is/union-of].isUnionOf|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. * @@ -246,8 +246,8 @@ export const is: { /** * 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[]`. + * Use {@linkcode [is/literal].isLiteral|isLiteral} to check if the type of `x` is a literal type. + * Use {@linkcode [is/literal-one-of].isLiteralOneOf|isLiteralOneOf} to check if the type of `x` is one of the literal type of {@linkcode [type].Primitive|Primitive[]}. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * @@ -265,8 +265,8 @@ export const is: { /** * 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`. + * Use {@linkcode [is/literal].isLiteral|isLiteral} to check if the type of `x` is a literal type. + * Use {@linkcode [is/literal-of].isLiteralOf|isLiteralOf} to check if the type of `x` is a literal type of {@linkcode [type].Primitive|Primitive}. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * @@ -284,7 +284,7 @@ export const is: { /** * Return `true` if the type of `x` is `Map`. * - * Use {@linkcode isMapOf} to check if the type of `x` is a map of `T`. + * Use {@linkcode [is/map-of].isMapOf|isMapOf} to check if the type of `x` is a map of `T`. * * ```ts * import { is } from "@core/unknownutil"; @@ -299,7 +299,7 @@ export const is: { /** * 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`. + * Use {@linkcode [is/map].isMap|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. * @@ -329,8 +329,8 @@ export const is: { /** * 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`. + * Use {@linkcode [is/undefined].isUndefined|isUndefined} to check if the type of `x` is `undefined`. + * Use {@linkcode [is/nullish].isNullish|isNullish} to check if the type of `x` is `null` or `undefined`. * * ```ts * import { is } from "@core/unknownutil"; @@ -345,8 +345,8 @@ export const is: { /** * 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`. + * Use {@linkcode [is/null].isNull|isNull} to check if the type of `x` is `null`. + * Use {@linkcode [is/undefined].isUndefined|isUndefined} to check if the type of `x` is `undefined`. * * ```ts * import { is } from "@core/unknownutil"; @@ -374,13 +374,13 @@ export const is: { /** * Return a type predicate function that returns `true` if the type of `x` is `ObjectOf`. * - * Use {@linkcode isRecordOf} if you want to check if the type of `x` is a record of `T`. + * Use {@linkcode [is/record-of].isRecordOf|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 in `predObj`, the property becomes optional. - * If {@linkcode asReadonly} is specified in the predicate function in `predObj`, the property becomes readonly. + * If {@linkcode [as/optional].asOptional|asOptional} is specified in the predicate function in `predObj`, the property becomes optional. + * If {@linkcode [as/readonly].asReadonly|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. + * Use {@linkcode [is/strict-of].isStrictOf|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. * @@ -405,14 +405,14 @@ export const is: { * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * @@ -434,7 +434,8 @@ export const is: { /** * Return a type predicate function that returns `true` if the type of `x` is `ParametersOf` or `ParametersOf`. * - * This is similar to {@linkcode isTupleOf}, but if {@linkcode asOptional} is specified at the trailing, the trailing elements becomes optional and makes variable-length tuple. + * This is similar to {@linkcode [is/tuple].isTupleOf|isTupleOf}, but if {@linkcode [as/optional].asOptional|asOptional} + * is specified at the trailing, the trailing elements becomes optional and makes variable-length tuple. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * @@ -494,14 +495,14 @@ export const is: { * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * @@ -525,14 +526,14 @@ export const is: { * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * @@ -567,6 +568,17 @@ export const is: { /** * Return a type predicate function that returns `true` if the type of `x` is `Readonly>`. * + * It only supports modifing a predicate function annotated with `IsPredObj`, usually returned by the followings + * + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript @@ -588,7 +600,7 @@ export const is: { * Return `true` if the type of `x` satisfies `Record`. * * Note that this function returns `true` for ambiguous instances like `Set`, `Map`, `Date`, `Promise`, etc. - * Use {@linkcode isRecordObject} instead if you want to check if `x` is an instance of `Object`. + * Use {@linkcode [is/record-object].isRecordObject|isRecordObject} instead if you want to check if `x` is an instance of `Object`. * * ```ts * import { is } from "@core/unknownutil"; @@ -609,7 +621,7 @@ export const is: { * Return `true` if the type of `x` is an object instance that satisfies `Record`. * * Note that this function check if the `x` is an instance of `Object`. - * Use {@linkcode isRecord} instead if you want to check if the `x` satisfies the `Record` type. + * Use {@linkcode [is/record].isRecord|isRecord} instead if you want to check if the `x` satisfies the `Record` type. * * ```ts * import { is } from "@core/unknownutil"; @@ -630,7 +642,7 @@ export const is: { * Return a type predicate function that returns `true` if the type of `x` is an Object instance that satisfies `Record`. * * 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. + * Use {@linkcode [is/record-of].isRecordOf|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. * @@ -661,7 +673,7 @@ export const is: { * Return a type predicate function that returns `true` if the type of `x` satisfies `Record`. * * 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`. + * Use {@linkcode [is/record-object-of].isRecordObjectOf|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. * @@ -693,14 +705,14 @@ export const is: { * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * @@ -722,7 +734,7 @@ export const is: { /** * Return `true` if the type of `x` is `Set`. * - * Use {@linkcode isSetOf} to check if the type of `x` is a set of `T`. + * Use {@linkcode [is/set-of].isSetOf|isSetOf} to check if the type of `x` is a set of `T`. * * ```ts * import { is } from "@core/unknownutil"; @@ -737,7 +749,7 @@ export const is: { /** * 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`. + * Use {@linkcode [is/set].isSet|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. * @@ -757,14 +769,14 @@ export const is: { * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * @@ -812,6 +824,9 @@ export const is: { /** * Return `true` if the type of `x` is `function` (non async function). * + * Use {@linkcode [is/function].isFunction|isFunction} to check if the type of `x` is a function. + * Use {@linkcode [is/async-function].isAsyncFunction|isAsyncFunction} to check if the type of `x` is an asynchronous function. + * * ```ts * import { is } from "@core/unknownutil"; * @@ -825,7 +840,7 @@ export const is: { /** * Return a type predicate function that returns `true` if the type of `x` is `TupleOf`. * - * Use {@linkcode isUniformTupleOf} to check if the type of `x` is a tuple of uniform types. + * Use {@linkcode [is/uniform-tuple-of].isUniformTupleOf|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. * @@ -909,7 +924,7 @@ export const is: { /** * 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`. + * Use {@linkcode [is/tuple-of].isTupleOf|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. * @@ -939,7 +954,7 @@ export const is: { /** * 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`. + * Use {@linkcode [is/intersection-of].isIntersectionOf|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. * @@ -971,7 +986,7 @@ export const is: { /** * 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`. + * Use {@linkcode [is/any].isAny|isAny} to assume that the type of `x` is `any`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/mod_test.ts b/is/mod_test.ts index 7276c9e..0a2d985 100644 --- a/is/mod_test.ts +++ b/is/mod_test.ts @@ -4,6 +4,8 @@ import { is } from "./mod.ts"; const excludes = [ "mod.ts", + "_*.ts", + "*_bench.ts", "*_test.ts", ]; diff --git a/is/null.ts b/is/null.ts index a4d8a15..b4fe65c 100644 --- a/is/null.ts +++ b/is/null.ts @@ -1,8 +1,8 @@ /** * 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`. + * Use {@linkcode [is/undefined].isUndefined|isUndefined} to check if the type of `x` is `undefined`. + * Use {@linkcode [is/nullish].isNullish|isNullish} to check if the type of `x` is `null` or `undefined`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/null_bench.ts b/is/null_bench.ts new file mode 100644 index 0000000..a6ac002 --- /dev/null +++ b/is/null_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isNull as isNull420 } from "jsr:@core/unknownutil@4.2.0/is/null"; +import { isNull } from "./null.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = null; +const negative: unknown = undefined; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isNull(positive))); + }, + group: "isNull (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isNull(negative))); + }, + group: "isNull (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isNull420(positive))); + }, + group: "isNull (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isNull420(negative))); + }, + group: "isNull (negative)", +}); diff --git a/is/nullish.ts b/is/nullish.ts index d462fba..eaaebb1 100644 --- a/is/nullish.ts +++ b/is/nullish.ts @@ -1,8 +1,8 @@ /** * 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`. + * Use {@linkcode [is/null].isNull|isNull} to check if the type of `x` is `null`. + * Use {@linkcode [is/undefined].isUndefined|isUndefined} to check if the type of `x` is `undefined`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/nullish_bench.ts b/is/nullish_bench.ts new file mode 100644 index 0000000..4eaf3ad --- /dev/null +++ b/is/nullish_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isNullish as isNullish420 } from "jsr:@core/unknownutil@4.2.0/is/nullish"; +import { isNullish } from "./nullish.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = null; +const negative: unknown = 0; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isNullish(positive))); + }, + group: "isNullish (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isNullish(negative))); + }, + group: "isNullish (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isNullish420(positive))); + }, + group: "isNullish (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isNullish420(negative))); + }, + group: "isNullish (negative)", +}); diff --git a/is/number_bench.ts b/is/number_bench.ts new file mode 100644 index 0000000..aeadf80 --- /dev/null +++ b/is/number_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isNumber as isNumber420 } from "jsr:@core/unknownutil@4.2.0/is/number"; +import { isNumber } from "./number.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = 0; +const negative: unknown = ""; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isNumber(positive))); + }, + group: "isNumber (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isNumber(negative))); + }, + group: "isNumber (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isNumber420(positive))); + }, + group: "isNumber (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isNumber420(negative))); + }, + group: "isNumber (negative)", +}); diff --git a/is/object_of.ts b/is/object_of.ts index 7be8ca9..0137696 100644 --- a/is/object_of.ts +++ b/is/object_of.ts @@ -11,13 +11,13 @@ import type { Predicate } from "../type.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `ObjectOf`. * - * Use {@linkcode isRecordOf} if you want to check if the type of `x` is a record of `T`. + * Use {@linkcode [is/record-of].isRecordOf|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 in `predObj`, the property becomes optional. - * If {@linkcode asReadonly} is specified in the predicate function in `predObj`, the property becomes readonly. + * If {@linkcode [as/optional].asOptional|asOptional} is specified in the predicate function in `predObj`, the property becomes optional. + * If {@linkcode [as/readonly].asReadonly|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. + * Use {@linkcode [is/strict-of].isStrictOf|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. * diff --git a/is/object_of_bench.ts b/is/object_of_bench.ts new file mode 100644 index 0000000..72caf7a --- /dev/null +++ b/is/object_of_bench.ts @@ -0,0 +1,126 @@ +import { assert } from "@std/assert"; +import { isObjectOf as isObjectOf420 } from "jsr:@core/unknownutil@4.2.0/is/object-of"; +import { isObjectOf } from "./object_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "", b: 0 }; +const positive10: unknown = Object.assign( + { a: "", b: 0 }, + Array.from({ length: 10 }), +); +const positive1000: unknown = Object.assign( + { a: "", b: 0 }, + Array.from({ length: 1000 }), +); +const negative: unknown = {}; +const negative10: unknown = Object.assign( + {}, + Array.from({ length: 10 }), +); +const negative1000: unknown = Object.assign( + {}, + Array.from({ length: 1000 }), +); + +const predObj = { + a: (x: unknown): x is string => typeof x === "string", + b: (x: unknown): x is number => typeof x === "number", +}; +const pred420 = isObjectOf420(predObj); +const pred = isObjectOf(predObj); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isObjectOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isObjectOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isObjectOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isObjectOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isObjectOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isObjectOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isObjectOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isObjectOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isObjectOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isObjectOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isObjectOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isObjectOf (negative 1000)", +}); diff --git a/is/omit_of.ts b/is/omit_of.ts index 242b355..c60c475 100644 --- a/is/omit_of.ts +++ b/is/omit_of.ts @@ -8,14 +8,14 @@ import { isObjectOf } from "./object_of.ts"; * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/is/omit_of_bench.ts b/is/omit_of_bench.ts new file mode 100644 index 0000000..719fc53 --- /dev/null +++ b/is/omit_of_bench.ts @@ -0,0 +1,127 @@ +import { assert } from "@std/assert"; +import { isObjectOf } from "./object_of.ts"; +import { isOmitOf as isOmitOf420 } from "jsr:@core/unknownutil@4.2.0/is/omit-of"; +import { isOmitOf } from "./omit_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "" }; +const positive10: unknown = Object.assign( + { a: "" }, + Array.from({ length: 10 }), +); +const positive1000: unknown = Object.assign( + { a: "" }, + Array.from({ length: 1000 }), +); +const negative: unknown = {}; +const negative10: unknown = Object.assign( + {}, + Array.from({ length: 10 }), +); +const negative1000: unknown = Object.assign( + {}, + Array.from({ length: 1000 }), +); + +const predOrig = isObjectOf({ + a: (x: unknown): x is string => typeof x === "string", + b: (x: unknown): x is number => typeof x === "number", +}); +const pred420 = isOmitOf420(predOrig, ["b"]); +const pred = isOmitOf(predOrig, ["b"]); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isOmitOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isOmitOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isOmitOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isOmitOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isOmitOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isOmitOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isOmitOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isOmitOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isOmitOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isOmitOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isOmitOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isOmitOf (negative 1000)", +}); diff --git a/is/parameters_of.ts b/is/parameters_of.ts index a202ca7..39134dd 100644 --- a/is/parameters_of.ts +++ b/is/parameters_of.ts @@ -7,7 +7,8 @@ import { isArray } from "./array.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `ParametersOf` or `ParametersOf`. * - * This is similar to {@linkcode isTupleOf}, but if {@linkcode asOptional} is specified at the trailing, the trailing elements becomes optional and makes variable-length tuple. + * This is similar to {@linkcode [is/tuple].isTupleOf|isTupleOf}, but if {@linkcode [as/optional].asOptional|asOptional} + * is specified at the trailing, the trailing elements becomes optional and makes variable-length tuple. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/is/parameters_of_bench.ts b/is/parameters_of_bench.ts new file mode 100644 index 0000000..a6e8d78 --- /dev/null +++ b/is/parameters_of_bench.ts @@ -0,0 +1,115 @@ +import { assert } from "@std/assert"; +import { isParametersOf as isParametersOf420 } from "jsr:@core/unknownutil@4.2.0/is/parameters-of"; +import { isParametersOf } from "./parameters_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = ["", 0]; +const positive10: unknown = ["", 0, ...Array.from({ length: 10 })]; +const positive1000: unknown = ["", 0, ...Array.from({ length: 1000 })]; +const negative: unknown = []; +const negative10: unknown = Array.from({ length: 10 }); +const negative1000: unknown = Array.from({ length: 1000 }); + +const predTup = [ + (x: unknown): x is string => typeof x === "string", + (x: unknown): x is number => typeof x === "number", +] as const; +const predElse = (_x: unknown): _x is number[] => true; +const pred420 = isParametersOf420(predTup, predElse); +const pred = isParametersOf(predTup, predElse); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isParametersOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isParametersOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isParametersOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isParametersOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isParametersOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isParametersOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isParametersOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isParametersOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isParametersOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isParametersOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isParametersOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isParametersOf (negative 1000)", +}); diff --git a/is/partial_of.ts b/is/partial_of.ts index 56e1395..19c6e0d 100644 --- a/is/partial_of.ts +++ b/is/partial_of.ts @@ -9,14 +9,14 @@ import { isObjectOf } from "./object_of.ts"; * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/is/partial_of_bench.ts b/is/partial_of_bench.ts new file mode 100644 index 0000000..f556c07 --- /dev/null +++ b/is/partial_of_bench.ts @@ -0,0 +1,127 @@ +import { assert } from "@std/assert"; +import { isObjectOf } from "./object_of.ts"; +import { isPartialOf as isPartialOf420 } from "jsr:@core/unknownutil@4.2.0/is/partial-of"; +import { isPartialOf } from "./partial_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "" }; +const positive10: unknown = Object.assign( + { a: "" }, + Array.from({ length: 10 }), +); +const positive1000: unknown = Object.assign( + { a: "" }, + Array.from({ length: 1000 }), +); +const negative: unknown = []; +const negative10: unknown = Object.assign( + [], + Array.from({ length: 10 }), +); +const negative1000: unknown = Object.assign( + [], + Array.from({ length: 1000 }), +); + +const predOrig = isObjectOf({ + a: (x: unknown): x is string => typeof x === "string", + b: (x: unknown): x is number => typeof x === "number", +}); +const pred420 = isPartialOf420(predOrig); +const pred = isPartialOf(predOrig); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isPartialOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isPartialOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isPartialOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isPartialOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isPartialOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isPartialOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isPartialOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isPartialOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isPartialOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isPartialOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isPartialOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isPartialOf (negative 1000)", +}); diff --git a/is/pick_of.ts b/is/pick_of.ts index 3ac46c4..32fb723 100644 --- a/is/pick_of.ts +++ b/is/pick_of.ts @@ -8,14 +8,14 @@ import { isObjectOf } from "./object_of.ts"; * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/is/pick_of_bench.ts b/is/pick_of_bench.ts new file mode 100644 index 0000000..305fea7 --- /dev/null +++ b/is/pick_of_bench.ts @@ -0,0 +1,127 @@ +import { assert } from "@std/assert"; +import { isObjectOf } from "./object_of.ts"; +import { isPickOf as isPickOf420 } from "jsr:@core/unknownutil@4.2.0/is/pick-of"; +import { isPickOf } from "./pick_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "" }; +const positive10: unknown = Object.assign( + { a: "" }, + Array.from({ length: 10 }), +); +const positive1000: unknown = Object.assign( + { a: "" }, + Array.from({ length: 1000 }), +); +const negative: unknown = {}; +const negative10: unknown = Object.assign( + {}, + Array.from({ length: 10 }), +); +const negative1000: unknown = Object.assign( + {}, + Array.from({ length: 1000 }), +); + +const predOrig = isObjectOf({ + a: (x: unknown): x is string => typeof x === "string", + b: (x: unknown): x is number => typeof x === "number", +}); +const pred420 = isPickOf420(predOrig, ["a"]); +const pred = isPickOf(predOrig, ["a"]); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isPickOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isPickOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isPickOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isPickOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isPickOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isPickOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isPickOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isPickOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isPickOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isPickOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isPickOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isPickOf (negative 1000)", +}); diff --git a/is/primitive_bench.ts b/is/primitive_bench.ts new file mode 100644 index 0000000..55a975e --- /dev/null +++ b/is/primitive_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isPrimitive as isPrimitive420 } from "jsr:@core/unknownutil@4.2.0/is/primitive"; +import { isPrimitive } from "./primitive.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = 0; +const negative: unknown = {}; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isPrimitive(positive))); + }, + group: "isPrimitive (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isPrimitive(negative))); + }, + group: "isPrimitive (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isPrimitive420(positive))); + }, + group: "isPrimitive (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isPrimitive420(negative))); + }, + group: "isPrimitive (negative)", +}); diff --git a/is/readonly_of.ts b/is/readonly_of.ts index c9e2671..ea548bb 100644 --- a/is/readonly_of.ts +++ b/is/readonly_of.ts @@ -5,6 +5,17 @@ import type { Predicate } from "../type.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `Readonly>`. * + * It only supports modifing a predicate function annotated with `IsPredObj`, usually returned by the followings + * + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} + * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript diff --git a/is/readonly_of_bench.ts b/is/readonly_of_bench.ts new file mode 100644 index 0000000..1fea1ea --- /dev/null +++ b/is/readonly_of_bench.ts @@ -0,0 +1,127 @@ +import { assert } from "@std/assert"; +import { isObjectOf } from "./object_of.ts"; +import { isReadonlyOf as isReadonlyOf420 } from "jsr:@core/unknownutil@4.2.0/is/readonly-of"; +import { isReadonlyOf } from "./readonly_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "", b: 0 }; +const positive10: unknown = Object.assign( + { a: "", b: 0 }, + Array.from({ length: 10 }), +); +const positive1000: unknown = Object.assign( + { a: "", b: 0 }, + Array.from({ length: 1000 }), +); +const negative: unknown = {}; +const negative10: unknown = Object.assign( + {}, + Array.from({ length: 10 }), +); +const negative1000: unknown = Object.assign( + {}, + Array.from({ length: 1000 }), +); + +const predOrig = isObjectOf({ + a: (x: unknown): x is string => typeof x === "string", + b: (x: unknown): x is number => typeof x === "number", +}); +const pred420 = isReadonlyOf420(predOrig); +const pred = isReadonlyOf(predOrig); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isReadonlyOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isReadonlyOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isReadonlyOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isReadonlyOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isReadonlyOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isReadonlyOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isReadonlyOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isReadonlyOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isReadonlyOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isReadonlyOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isReadonlyOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isReadonlyOf (negative 1000)", +}); diff --git a/is/record.ts b/is/record.ts index fc691f7..318ccfa 100644 --- a/is/record.ts +++ b/is/record.ts @@ -2,7 +2,7 @@ * Return `true` if the type of `x` satisfies `Record`. * * Note that this function returns `true` for ambiguous instances like `Set`, `Map`, `Date`, `Promise`, etc. - * Use {@linkcode isRecordObject} instead if you want to check if `x` is an instance of `Object`. + * Use {@linkcode [is/record-object].isRecordObject|isRecordObject} instead if you want to check if `x` is an instance of `Object`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/record_bench.ts b/is/record_bench.ts new file mode 100644 index 0000000..3281908 --- /dev/null +++ b/is/record_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isRecord as isRecord420 } from "jsr:@core/unknownutil@4.2.0/is/record"; +import { isRecord } from "./record.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = {}; +const negative: unknown = 0; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isRecord(positive))); + }, + group: "isRecord (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isRecord(negative))); + }, + group: "isRecord (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isRecord420(positive))); + }, + group: "isRecord (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isRecord420(negative))); + }, + group: "isRecord (negative)", +}); diff --git a/is/record_object.ts b/is/record_object.ts index 2281809..86a5633 100644 --- a/is/record_object.ts +++ b/is/record_object.ts @@ -2,7 +2,7 @@ * Return `true` if the type of `x` is an object instance that satisfies `Record`. * * Note that this function check if the `x` is an instance of `Object`. - * Use {@linkcode isRecord} instead if you want to check if the `x` satisfies the `Record` type. + * Use {@linkcode [is/record].isRecord|isRecord} instead if you want to check if the `x` satisfies the `Record` type. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/record_object_bench.ts b/is/record_object_bench.ts new file mode 100644 index 0000000..96c8058 --- /dev/null +++ b/is/record_object_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isRecordObject as isRecordObject420 } from "jsr:@core/unknownutil@4.2.0/is/record-object"; +import { isRecordObject } from "./record_object.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = {}; +const negative: unknown = new Map(); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isRecordObject(positive))); + }, + group: "isRecordObject (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isRecordObject(negative))); + }, + group: "isRecordObject (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isRecordObject420(positive))); + }, + group: "isRecordObject (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isRecordObject420(negative))); + }, + group: "isRecordObject (negative)", +}); diff --git a/is/record_object_of.ts b/is/record_object_of.ts index 46d22a2..f6d3452 100644 --- a/is/record_object_of.ts +++ b/is/record_object_of.ts @@ -6,7 +6,7 @@ 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`. * * 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. + * Use {@linkcode [is/record-of].isRecordOf|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. * diff --git a/is/record_object_of_bench.ts b/is/record_object_of_bench.ts new file mode 100644 index 0000000..bb62c29 --- /dev/null +++ b/is/record_object_of_bench.ts @@ -0,0 +1,226 @@ +import { assert } from "@std/assert"; +import { isRecordObjectOf as isRecordObjectOf420 } from "jsr:@core/unknownutil@4.2.0/is/record-object-of"; +import { isRecordObjectOf } from "./record_object_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = {}; +const positive10: unknown = Object.fromEntries( + Array.from({ length: 10 }).map((_, i) => [i.toString(), ""]), +); +const positive1000: unknown = Object.fromEntries( + Array.from({ length: 1000 }).map((_, i) => [i.toString(), ""]), +); +const negative: unknown = { "": 0 }; +const negative10: unknown = Object.fromEntries( + Array.from({ length: 10 }).map((_, i) => [i.toString(), 0]), +); +const negative1000: unknown = Object.fromEntries( + Array.from({ length: 1000 }).map((_, i) => [i.toString(), 0]), +); + +const pred1420 = isRecordObjectOf420((x: unknown): x is string => + typeof x === "string" +); +const pred2420 = isRecordObjectOf420( + (x: unknown): x is string => typeof x === "string", + (x: unknown): x is string => typeof x === "string", +); +const pred1 = isRecordObjectOf((x: unknown): x is string => + typeof x === "string" +); +const pred2 = isRecordObjectOf( + (x: unknown): x is string => typeof x === "string", + (x: unknown): x is string => typeof x === "string", +); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive))); + }, + group: "isRecordObjectOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive10))); + }, + group: "isRecordObjectOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive1000))); + }, + group: "isRecordObjectOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative))); + }, + group: "isRecordObjectOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative10))); + }, + group: "isRecordObjectOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative1000))); + }, + group: "isRecordObjectOf (negative 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive))); + }, + group: "isRecordObjectOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive10))); + }, + group: "isRecordObjectOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive1000))); + }, + group: "isRecordObjectOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative))); + }, + group: "isRecordObjectOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative10))); + }, + group: "isRecordObjectOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative1000))); + }, + group: "isRecordObjectOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive))); + }, + group: "isRecordObjectOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive10))); + }, + group: "isRecordObjectOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive1000))); + }, + group: "isRecordObjectOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative))); + }, + group: "isRecordObjectOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative10))); + }, + group: "isRecordObjectOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative1000))); + }, + group: "isRecordObjectOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive))); + }, + group: "isRecordObjectOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive10))); + }, + group: "isRecordObjectOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive1000))); + }, + group: "isRecordObjectOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative))); + }, + group: "isRecordObjectOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative10))); + }, + group: "isRecordObjectOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative1000))); + }, + group: "isRecordObjectOf (negative 1000)", +}); diff --git a/is/record_of.ts b/is/record_of.ts index 1d96cd2..275ef15 100644 --- a/is/record_of.ts +++ b/is/record_of.ts @@ -6,7 +6,7 @@ import { isRecord } from "./record.ts"; * Return a type predicate function that returns `true` if the type of `x` satisfies `Record`. * * 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`. + * Use {@linkcode [is/record-object-of].isRecordObjectOf|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. * diff --git a/is/record_of_bench.ts b/is/record_of_bench.ts new file mode 100644 index 0000000..b2131a7 --- /dev/null +++ b/is/record_of_bench.ts @@ -0,0 +1,224 @@ +import { assert } from "@std/assert"; +import { isRecordOf as isRecordOf420 } from "jsr:@core/unknownutil@4.2.0/is/record-of"; +import { isRecordOf } from "./record_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = {}; +const positive10: unknown = Object.fromEntries( + Array.from({ length: 10 }).map((_, i) => [i.toString(), ""]), +); +const positive1000: unknown = Object.fromEntries( + Array.from({ length: 1000 }).map((_, i) => [i.toString(), ""]), +); +const negative: unknown = { "": 0 }; +const negative10: unknown = Object.fromEntries( + Array.from({ length: 10 }).map((_, i) => [i.toString(), 0]), +); +const negative1000: unknown = Object.fromEntries( + Array.from({ length: 1000 }).map((_, i) => [i.toString(), 0]), +); + +const pred1420 = isRecordOf420((x: unknown): x is string => + typeof x === "string" +); +const pred2420 = isRecordOf420( + (x: unknown): x is string => typeof x === "string", + (x: unknown): x is string => typeof x === "string", +); +const pred1 = isRecordOf((x: unknown): x is string => typeof x === "string"); +const pred2 = isRecordOf( + (x: unknown): x is string => typeof x === "string", + (x: unknown): x is string => typeof x === "string", +); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive))); + }, + group: "isRecordOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive10))); + }, + group: "isRecordOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred1(positive1000))); + }, + group: "isRecordOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative))); + }, + group: "isRecordOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative10))); + }, + group: "isRecordOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred1(negative1000))); + }, + group: "isRecordOf (negative 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive))); + }, + group: "isRecordOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive10))); + }, + group: "isRecordOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred2(positive1000))); + }, + group: "isRecordOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative))); + }, + group: "isRecordOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative10))); + }, + group: "isRecordOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred2(negative1000))); + }, + group: "isRecordOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive))); + }, + group: "isRecordOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive10))); + }, + group: "isRecordOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred1420(positive1000))); + }, + group: "isRecordOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative))); + }, + group: "isRecordOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative10))); + }, + group: "isRecordOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred1420(negative1000))); + }, + group: "isRecordOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive))); + }, + group: "isRecordOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive10))); + }, + group: "isRecordOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred2420(positive1000))); + }, + group: "isRecordOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative))); + }, + group: "isRecordOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative10))); + }, + group: "isRecordOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred2420(negative1000))); + }, + group: "isRecordOf (negative 1000)", +}); diff --git a/is/required_of.ts b/is/required_of.ts index 310ba2a..77fc75f 100644 --- a/is/required_of.ts +++ b/is/required_of.ts @@ -9,14 +9,14 @@ import { isObjectOf } from "./object_of.ts"; * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/is/required_of_bench.ts b/is/required_of_bench.ts new file mode 100644 index 0000000..2c193c1 --- /dev/null +++ b/is/required_of_bench.ts @@ -0,0 +1,127 @@ +import { assert } from "@std/assert"; +import { isObjectOf } from "./object_of.ts"; +import { isRequiredOf as isRequiredOf420 } from "jsr:@core/unknownutil@4.2.0/is/required-of"; +import { isRequiredOf } from "./required_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "", b: 0 }; +const positive10: unknown = Object.assign( + { a: "", b: 0 }, + Array.from({ length: 10 }), +); +const positive1000: unknown = Object.assign( + { a: "", b: 0 }, + Array.from({ length: 1000 }), +); +const negative: unknown = {}; +const negative10: unknown = Object.assign( + {}, + Array.from({ length: 10 }), +); +const negative1000: unknown = Object.assign( + {}, + Array.from({ length: 1000 }), +); + +const predOrig = isObjectOf({ + a: (x: unknown): x is string => typeof x === "string", + b: (x: unknown): x is number => typeof x === "number", +}); +const pred420 = isRequiredOf420(predOrig); +const pred = isRequiredOf(predOrig); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isRequiredOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isRequiredOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isRequiredOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isRequiredOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isRequiredOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isRequiredOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isRequiredOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isRequiredOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isRequiredOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isRequiredOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isRequiredOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isRequiredOf (negative 1000)", +}); diff --git a/is/set.ts b/is/set.ts index fe5a308..5d19dd7 100644 --- a/is/set.ts +++ b/is/set.ts @@ -1,7 +1,7 @@ /** * Return `true` if the type of `x` is `Set`. * - * Use {@linkcode isSetOf} to check if the type of `x` is a set of `T`. + * Use {@linkcode [is/set-of].isSetOf|isSetOf} to check if the type of `x` is a set of `T`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/set_bench.ts b/is/set_bench.ts new file mode 100644 index 0000000..bd1439d --- /dev/null +++ b/is/set_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isSet as isSet420 } from "jsr:@core/unknownutil@4.2.0/is/set"; +import { isSet } from "./set.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = new Set(); +const negative: unknown = []; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isSet(positive))); + }, + group: "isSet (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isSet(negative))); + }, + group: "isSet (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isSet420(positive))); + }, + group: "isSet (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isSet420(negative))); + }, + group: "isSet (negative)", +}); diff --git a/is/set_of.ts b/is/set_of.ts index 0f45ffb..5a69102 100644 --- a/is/set_of.ts +++ b/is/set_of.ts @@ -5,7 +5,7 @@ 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`. + * Use {@linkcode [is/set].isSet|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. * diff --git a/is/set_of_bench.ts b/is/set_of_bench.ts new file mode 100644 index 0000000..e93581b --- /dev/null +++ b/is/set_of_bench.ts @@ -0,0 +1,118 @@ +import { assert } from "@std/assert"; +import { isSetOf as isSetOf420 } from "jsr:@core/unknownutil@4.2.0/is/set-of"; +import { isSetOf } from "./set_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = new Set(); +const positive10: unknown = new Set( + Array.from({ length: 10 }).map((_, i) => i.toString()), +); +const positive1000: unknown = new Set( + Array.from({ length: 1000 }).map((_, i) => i.toString()), +); +const negative: unknown = { "": 0 }; +const negative10: unknown = new Set( + Array.from({ length: 10 }).map((_, i) => i), +); +const negative1000: unknown = new Set( + Array.from({ length: 1000 }).map((_, i) => i), +); + +const pred420 = isSetOf420((x: unknown): x is string => typeof x === "string"); +const pred = isSetOf((x: unknown): x is string => typeof x === "string"); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isSetOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isSetOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isSetOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isSetOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isSetOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isSetOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isSetOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isSetOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isSetOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isSetOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isSetOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isSetOf (negative 1000)", +}); diff --git a/is/strict_of.ts b/is/strict_of.ts index a3f50c3..0b342f3 100644 --- a/is/strict_of.ts +++ b/is/strict_of.ts @@ -7,14 +7,14 @@ import type { Predicate } from "../type.ts"; * * 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} + * - {@linkcode [is/intersection-of].isIntersectionOf|isIntersectionOf} + * - {@linkcode [is/object-of].isObjectOf|isObjectOf} + * - {@linkcode [is/omit-of].isOmitOf|isOmitOf} + * - {@linkcode [is/partial-of].isPartialOf|isPartialOf} + * - {@linkcode [is/pick-of].isPickOf|isPickOf} + * - {@linkcode [is/readonly-of].isReadonlyOf|isReadonlyOf} + * - {@linkcode [is/required-of].isRequiredOf|isRequiredOf} + * - {@linkcode [is/strict-of].isStrictOf|isStrictOf} * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * diff --git a/is/strict_of_bench.ts b/is/strict_of_bench.ts new file mode 100644 index 0000000..b2d4162 --- /dev/null +++ b/is/strict_of_bench.ts @@ -0,0 +1,47 @@ +import { assert } from "@std/assert"; +import { isObjectOf } from "./object_of.ts"; +import { isStrictOf as isStrictOf420 } from "jsr:@core/unknownutil@4.2.0/is/strict-of"; +import { isStrictOf } from "./strict_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "", b: 0 }; +const negative: unknown = { a: "", b: 0, c: true }; + +const predOrig = isObjectOf({ + a: (x: unknown): x is string => typeof x === "string", + b: (x: unknown): x is number => typeof x === "number", +}); +const pred420 = isStrictOf420(predOrig); +const pred = isStrictOf(predOrig); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isStrictOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isStrictOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isStrictOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isStrictOf (negative)", +}); diff --git a/is/string_bench.ts b/is/string_bench.ts new file mode 100644 index 0000000..fab0588 --- /dev/null +++ b/is/string_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isString as isString420 } from "jsr:@core/unknownutil@4.2.0/is/string"; +import { isString } from "./string.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = ""; +const negative: unknown = 0; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isString(positive))); + }, + group: "isString (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isString(negative))); + }, + group: "isString (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isString420(positive))); + }, + group: "isString (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isString420(negative))); + }, + group: "isString (negative)", +}); diff --git a/is/symbol_bench.ts b/is/symbol_bench.ts new file mode 100644 index 0000000..93b323f --- /dev/null +++ b/is/symbol_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isSymbol as isSymbol420 } from "jsr:@core/unknownutil@4.2.0/is/symbol"; +import { isSymbol } from "./symbol.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = Symbol(); +const negative: unknown = 0; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isSymbol(positive))); + }, + group: "isSymbol (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isSymbol(negative))); + }, + group: "isSymbol (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isSymbol420(positive))); + }, + group: "isSymbol (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isSymbol420(negative))); + }, + group: "isSymbol (negative)", +}); diff --git a/is/sync_function.ts b/is/sync_function.ts index bf5bca4..ea22b41 100644 --- a/is/sync_function.ts +++ b/is/sync_function.ts @@ -3,6 +3,9 @@ const objectToString = Object.prototype.toString; /** * Return `true` if the type of `x` is `function` (non async function). * + * Use {@linkcode [is/function].isFunction|isFunction} to check if the type of `x` is a function. + * Use {@linkcode [is/async-function].isAsyncFunction|isAsyncFunction} to check if the type of `x` is an asynchronous function. + * * ```ts * import { is } from "@core/unknownutil"; * diff --git a/is/sync_function_bench.ts b/is/sync_function_bench.ts new file mode 100644 index 0000000..0c5a196 --- /dev/null +++ b/is/sync_function_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isSyncFunction as isSyncFunction420 } from "jsr:@core/unknownutil@4.2.0/is/sync-function"; +import { isSyncFunction } from "./sync_function.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = () => {}; +const negative: unknown = async () => {}; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isSyncFunction(positive))); + }, + group: "isSyncFunction (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isSyncFunction(negative))); + }, + group: "isSyncFunction (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isSyncFunction420(positive))); + }, + group: "isSyncFunction (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isSyncFunction420(negative))); + }, + group: "isSyncFunction (negative)", +}); diff --git a/is/tuple_of.ts b/is/tuple_of.ts index 1748484..c8f4565 100644 --- a/is/tuple_of.ts +++ b/is/tuple_of.ts @@ -5,7 +5,7 @@ import { isArray } from "./array.ts"; /** * Return a type predicate function that returns `true` if the type of `x` is `TupleOf`. * - * Use {@linkcode isUniformTupleOf} to check if the type of `x` is a tuple of uniform types. + * Use {@linkcode [is/uniform-tuple-of].isUniformTupleOf|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. * diff --git a/is/tuple_of_bench.ts b/is/tuple_of_bench.ts new file mode 100644 index 0000000..704593a --- /dev/null +++ b/is/tuple_of_bench.ts @@ -0,0 +1,115 @@ +import { assert } from "@std/assert"; +import { isTupleOf as isTupleOf420 } from "jsr:@core/unknownutil@4.2.0/is/tuple-of"; +import { isTupleOf } from "./tuple_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = ["", 0]; +const positive10: unknown = ["", 0, ...Array.from({ length: 10 })]; +const positive1000: unknown = ["", 0, ...Array.from({ length: 1000 })]; +const negative: unknown = []; +const negative10: unknown = Array.from({ length: 10 }); +const negative1000: unknown = Array.from({ length: 1000 }); + +const predTup = [ + (x: unknown): x is string => typeof x === "string", + (x: unknown): x is number => typeof x === "number", +] as const; +const predElse = (_x: unknown): _x is number[] => true; +const pred420 = isTupleOf420(predTup, predElse); +const pred = isTupleOf(predTup, predElse); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isTupleOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isTupleOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isTupleOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isTupleOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isTupleOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isTupleOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isTupleOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isTupleOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isTupleOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isTupleOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isTupleOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isTupleOf (negative 1000)", +}); diff --git a/is/undefined_bench.ts b/is/undefined_bench.ts new file mode 100644 index 0000000..44f545e --- /dev/null +++ b/is/undefined_bench.ts @@ -0,0 +1,39 @@ +import { assert } from "@std/assert"; +import { isUndefined as isUndefined420 } from "jsr:@core/unknownutil@4.2.0/is/undefined"; +import { isUndefined } from "./undefined.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = undefined; +const negative: unknown = 0; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isUndefined(positive))); + }, + group: "isUndefined (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !isUndefined(negative))); + }, + group: "isUndefined (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isUndefined420(positive))); + }, + group: "isUndefined (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !isUndefined420(negative))); + }, + group: "isUndefined (negative)", +}); diff --git a/is/uniform_tuple_of.ts b/is/uniform_tuple_of.ts index d007912..74581f1 100644 --- a/is/uniform_tuple_of.ts +++ b/is/uniform_tuple_of.ts @@ -5,7 +5,7 @@ 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`. + * Use {@linkcode [is/tuple-of].isTupleOf|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. * diff --git a/is/uniform_tuple_of_bench.ts b/is/uniform_tuple_of_bench.ts new file mode 100644 index 0000000..052f581 --- /dev/null +++ b/is/uniform_tuple_of_bench.ts @@ -0,0 +1,43 @@ +import { assert } from "@std/assert"; +import { isUniformTupleOf as isUniformTupleOf420 } from "jsr:@core/unknownutil@4.2.0/is/uniform-tuple-of"; +import { isUniformTupleOf } from "./uniform_tuple_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = [0, 0, 0]; +const negative: unknown = [0, 0, 0, 0]; + +const predElse = (_x: unknown): _x is number[] => true; +const pred420 = isUniformTupleOf420(3, predElse); +const pred = isUniformTupleOf(3, predElse); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isUniformTupleOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isUniformTupleOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isUniformTupleOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isUniformTupleOf (negative)", +}); diff --git a/is/union_of.ts b/is/union_of.ts index 9e898ec..8dd2674 100644 --- a/is/union_of.ts +++ b/is/union_of.ts @@ -5,7 +5,7 @@ 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`. + * Use {@linkcode [is/intersection-of].isIntersectionOf|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. * diff --git a/is/union_of_bench.ts b/is/union_of_bench.ts new file mode 100644 index 0000000..029ba93 --- /dev/null +++ b/is/union_of_bench.ts @@ -0,0 +1,128 @@ +import { assert } from "@std/assert"; +import { isObjectOf } from "./object_of.ts"; +import { isUnionOf as isUnionOf420 } from "jsr:@core/unknownutil@4.2.0/is/union-of"; +import { isUnionOf } from "./union_of.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = { a: "", b: 0, c: true }; +const positive10: unknown = Object.assign( + { a: "", b: 0, c: true }, + Array.from({ length: 10 }), +); +const positive1000: unknown = Object.assign( + { a: "", b: 0, c: true }, + Array.from({ length: 1000 }), +); +const negative: unknown = {}; +const negative10: unknown = Object.assign({}, Array.from({ length: 10 })); +const negative1000: unknown = Object.assign({}, Array.from({ length: 1000 })); + +const preds = [ + isObjectOf({ + a: (x: unknown): x is string => typeof x === "string", + }), + isObjectOf({ + b: (x: unknown): x is number => typeof x === "number", + }), + isObjectOf({ + c: (x: unknown): x is boolean => typeof x === "boolean", + }), +] as const; +const pred420 = isUnionOf420(preds); +const pred = isUnionOf(preds); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive))); + }, + group: "isUnionOf (positive)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive10))); + }, + group: "isUnionOf (positive 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => pred(positive1000))); + }, + group: "isUnionOf (positive 1000)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative))); + }, + group: "isUnionOf (negative)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative10))); + }, + group: "isUnionOf (negative 10)", +}); + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => !pred(negative1000))); + }, + group: "isUnionOf (negative 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive))); + }, + group: "isUnionOf (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive10))); + }, + group: "isUnionOf (positive 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => pred420(positive1000))); + }, + group: "isUnionOf (positive 1000)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative))); + }, + group: "isUnionOf (negative)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative10))); + }, + group: "isUnionOf (negative 10)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => !pred420(negative1000))); + }, + group: "isUnionOf (negative 1000)", +}); diff --git a/is/unknown.ts b/is/unknown.ts index e5de964..70f70eb 100644 --- a/is/unknown.ts +++ b/is/unknown.ts @@ -1,7 +1,7 @@ /** * 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`. + * Use {@linkcode [is/any].isAny|isAny} to assume that the type of `x` is `any`. * * ```ts * import { is } from "@core/unknownutil"; diff --git a/is/unknown_bench.ts b/is/unknown_bench.ts new file mode 100644 index 0000000..da38490 --- /dev/null +++ b/is/unknown_bench.ts @@ -0,0 +1,22 @@ +import { assert } from "@std/assert"; +import { isUnknown as isUnknown420 } from "jsr:@core/unknownutil@4.2.0/is/unknown"; +import { isUnknown } from "./unknown.ts"; + +const repeats = Array.from({ length: 100 }); +const positive: unknown = ""; + +Deno.bench({ + name: "current", + fn() { + assert(repeats.every(() => isUnknown(positive))); + }, + group: "isUnknown (positive)", +}); + +Deno.bench({ + name: "v4.2.0", + fn() { + assert(repeats.every(() => isUnknown420(positive))); + }, + group: "isUnknown (positive)", +}); diff --git a/mod_test.ts b/mod_test.ts index 87a64f0..0814744 100644 --- a/mod_test.ts +++ b/mod_test.ts @@ -6,6 +6,8 @@ import { is } from "./is/mod.ts"; const excludes = [ "mod.ts", + "_*.ts", + "*_bench.ts", "*_test.ts", ];