Skip to main content
Module

x/unknownutil/is.ts

🦕 A lightweight utility pack for handling unknown type
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851
import type { FlatType, TupleToIntersection, Writable } from "./_typeutil.ts";import { type GetMetadata, getMetadata, getPredicateFactoryMetadata, type PredicateFactoryMetadata, setPredicateFactoryMetadata, type WithMetadata,} from "./metadata.ts";
const objectToString = Object.prototype.toString;const primitiveSet = new Set([ "string", "number", "bigint", "boolean", "symbol",]);
/** * A type predicate function. */export type Predicate<T> = (x: unknown) => x is T;
/** * A type predicated by Predicate<T>. * * ```ts * import { is, type PredicateType } from "@core/unknownutil"; * * const isPerson = is.ObjectOf({ * name: is.String, * age: is.Number, * address: is.OptionalOf(is.String), * }); * * type Person = PredicateType<typeof isPerson>; * // Above is equivalent to the following type * // type Person = { * // name: string; * // age: number; * // address: string | undefined; * // }; */export type PredicateType<P> = P extends Predicate<infer T> ? T : never;
/** * Assume `x is `any` and always return `true` regardless of the type of `x`. * * ```ts * import { is } from "@core/unknownutil"; * * const a = "a"; * if (is.Any(a)) { * // a is narrowed to any * const _: any = a; * } * ``` */// deno-lint-ignore no-explicit-anyexport function isAny(_x: unknown): _x is any { return true;}
/** * Assume `x` is `unknown` and always return `true` regardless of the type of `x`. * * ```ts * import { is } from "@core/unknownutil"; * * const a = "a"; * if (is.Unknown(a)) { * // a is narrowed to unknown * const _: unknown = a; * } * ``` */export function isUnknown(_x: unknown): _x is unknown { return true;}
/** * Return `true` if the type of `x` is `string`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = "a"; * if (is.String(a)) { * // a is narrowed to string * const _: string = a; * } * ``` */export function isString(x: unknown): x is string { return typeof x === "string";}
/** * Return `true` if the type of `x` is `number`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = 0; * if (is.Number(a)) { * // a is narrowed to number * const _: number = a; * } * ``` */export function isNumber(x: unknown): x is number { return typeof x === "number";}
/** * Return `true` if the type of `x` is `bigint`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = 0n; * if (is.BigInt(a)) { * // a is narrowed to bigint * const _: bigint = a; * } * ``` */export function isBigInt(x: unknown): x is bigint { return typeof x === "bigint";}
/** * Return `true` if the type of `x` is `boolean`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = true; * if (is.Boolean(a)) { * // a is narrowed to boolean * const _: boolean = a; * } * ``` */export function isBoolean(x: unknown): x is boolean { return typeof x === "boolean";}
/** * Return `true` if the type of `x` is `unknown[]`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = [0, 1, 2]; * if (is.Array(a)) { * // a is narrowed to unknown[] * const _: unknown[] = a; * } * ``` */export function isArray( x: unknown,): x is unknown[] { return Array.isArray(x);}
/** * Return `true` if the type of `x` is `Set<unknown>`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = new Set([0, 1, 2]); * if (is.Set(a)) { * // a is narrowed to Set<unknown> * const _: Set<unknown> = a; * } * ``` */export function isSet(x: unknown): x is Set<unknown> { return x instanceof Set;}
/** * Return `true` if the type of `x` is an object instance that satisfies `Record<PropertyKey, unknown>`. * * Note that this function check if the `x` is an instance of `Object`. * Use `isRecordLike` instead if you want to check if the `x` satisfies the `Record<PropertyKey, unknown>` type. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = {"a": 0, "b": 1}; * if (is.RecordObject(a)) { * // a is narrowed to Record<PropertyKey, unknown> * const _: Record<PropertyKey, unknown> = a; * } * * const b: unknown = new Set(); * if (is.RecordObject(b)) { * // b is not a raw object, so it is not narrowed * } * ``` */export function isRecordObject( x: unknown,): x is Record<PropertyKey, unknown> { return x != null && typeof x === "object" && x.constructor === Object;}
/** * Return `true` if the type of `x` satisfies `Record<PropertyKey, unknown>`. * * Note that this function returns `true` for ambiguous instances like `Set`, `Map`, `Date`, `Promise`, etc. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = {"a": 0, "b": 1}; * if (is.Record(a)) { * // a is narrowed to Record<PropertyKey, unknown> * const _: Record<PropertyKey, unknown> = a; * } * * const b: unknown = new Set(); * if (is.Record(b)) { * // b is narrowed to Record<PropertyKey, unknown> * const _: Record<PropertyKey, unknown> = b; * } * ``` */export function isRecord( x: unknown,): x is Record<PropertyKey, unknown> { return x != null && !Array.isArray(x) && typeof x === "object";}
/** * Return `true` if the type of `x` is like `Record<PropertyKey, unknown>`. * * @deprecated Use `is.Record` instead. * ``` */export function isRecordLike( x: unknown,): x is Record<PropertyKey, unknown> { return x != null && !Array.isArray(x) && typeof x === "object";}
/** * Return `true` if the type of `x` is `Map<unknown, unknown>`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = new Map([["a", 0], ["b", 1]]); * if (is.Map(a)) { * // a is narrowed to Map<unknown, unknown> * const _: Map<unknown, unknown> = a; * } * ``` */export function isMap(x: unknown): x is Map<unknown, unknown> { return x instanceof Map;}
/** * Return `true` if the type of `x` is `function`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = () => {}; * if (is.Function(a)) { * // a is narrowed to (...args: unknown[]) => unknown * const _: ((...args: unknown[]) => unknown) = a; * } * ``` */export function isFunction(x: unknown): x is (...args: unknown[]) => unknown { return x instanceof Function;}
/** * Return `true` if the type of `x` is `function` (non async function). * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = () => {}; * if (is.Function(a)) { * // a is narrowed to (...args: unknown[]) => unknown * const _: ((...args: unknown[]) => unknown) = a; * } * ``` */export function isSyncFunction( x: unknown,): x is (...args: unknown[]) => unknown { return objectToString.call(x) === "[object Function]";}
/** * Return `true` if the type of `x` is `function` (async function). * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = async () => {}; * if (is.Function(a)) { * // a is narrowed to (...args: unknown[]) => Promise<unknown> * const _: ((...args: unknown[]) => unknown) = a; * } * ``` */export function isAsyncFunction( x: unknown,): x is (...args: unknown[]) => Promise<unknown> { return objectToString.call(x) === "[object AsyncFunction]";}
/** * Return `true` if the type of `x` is `null`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = null; * if (is.Null(a)) { * // a is narrowed to null * const _: null = a; * } * ``` */export function isNull(x: unknown): x is null { return x === null;}
/** * Return `true` if the type of `x` is `undefined`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = undefined; * if (is.Undefined(a)) { * // a is narrowed to undefined * const _: undefined = a; * } * ``` */export function isUndefined(x: unknown): x is undefined { return typeof x === "undefined";}
/** * Return `true` if the type of `x` is `null` or `undefined`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = null; * if (is.Nullish(a)) { * // a is narrowed to null | undefined * const _: (null | undefined) = a; * } * ``` */export function isNullish(x: unknown): x is null | undefined { return x == null;}
/** * Return `true` if the type of `x` is `symbol`. * * ```ts * import { is } from "@core/unknownutil"; * * const a: unknown = Symbol("symbol"); * if (is.Symbol(a)) { * // a is narrowed to symbol * const _: symbol = a; * } * ``` */export function isSymbol(x: unknown): x is symbol { return typeof x === "symbol";}
export type Primitive = | string | number | bigint | boolean | null | undefined | symbol;
/** * Return `true` if the type of `x` is `Primitive`. * * ```ts * import { is, Primitive } from "@core/unknownutil"; * * const a: unknown = 0; * if (is.Primitive(a)) { * // a is narrowed to Primitive * const _: Primitive = a; * } * ``` */export function isPrimitive(x: unknown): x is Primitive { return x == null || primitiveSet.has(typeof x);}
/** * Return `true` if the type of predicate function `x` is annotated as `Optional` */export function isOptional<P extends Predicate<unknown>>( x: P,): x is P & WithMetadata<IsOptionalOfMetadata> { const m = getMetadata(x); if (m == null) return false; return (m as PredicateFactoryMetadata).name === "isOptionalOf";}
/** * Return an `Optional` annotated type predicate function that returns `true` if the type of `x` is `T` or `undefined`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.OptionalOf(is.String); * const a: unknown = "a"; * if (isMyType(a)) { * // a is narrowed to string | undefined * const _: string | undefined = a; * } * ``` */export function isOptionalOf<T>( pred: Predicate<T>,): & Predicate<T | undefined> & WithMetadata<IsOptionalOfMetadata> { if (isOptional(pred)) { return pred as & Predicate<T | undefined> & WithMetadata<IsOptionalOfMetadata>; } return Object.defineProperties( setPredicateFactoryMetadata( (x: unknown): x is T | undefined => x === undefined || pred(x), { name: "isOptionalOf", args: [pred] }, ), { optional: { value: true as const } }, ) as & Predicate<T | undefined> & WithMetadata<IsOptionalOfMetadata>;}
type IsOptionalOfMetadata = { name: "isOptionalOf"; args: Parameters<typeof isOptionalOf>;};
/** * Return an `Optional` un-annotated type predicate function that returns `true` if the type of `x` is `T`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.UnwrapOptionalOf(is.OptionalOf(is.String)); * const a: unknown = "a"; * if (isMyType(a)) { * // a is narrowed to string * const _: string = a; * } * ``` */export function isUnwrapOptionalOf<P extends Predicate<unknown>>( pred: P,): UnwrapOptionalOf<P> { if (!isOptional(pred)) return pred as UnwrapOptionalOf<P>; const { args } = getPredicateFactoryMetadata(pred); return args[0] as UnwrapOptionalOf<P>;}
type UnwrapOptionalOf<T> = T extends Predicate<undefined | infer U> & WithMetadata<IsOptionalOfMetadata> ? Predicate<U> : T extends Predicate<unknown> ? T : never;
/** * Return `true` if the type of predicate function `x` is annotated as `Readonly` * * **This is unstable and may be removed in the future.** */export function isReadonly<P extends Predicate<unknown>>( x: P,): x is P & WithMetadata<IsReadonlyOfMetadata> { const m = getMetadata(x); if (m == null) return false; return (m as PredicateFactoryMetadata).name === "isReadonlyOf";}
/** * Return an `Readonly` annotated type predicate function that returns `true` if the type of `x` is `T`. * * **This is unstable and may be removed in the future.** * * Note that this function does nothing but annotate the predicate function as `Readonly`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ReadonlyOf(is.TupleOf([is.String, is.Number])); * const a: unknown = ["a", 1]; * if (isMyType(a)) { * // a is narrowed to readonly [string, number] * const _: readonly [string, number] = a; * } * ``` */export function isReadonlyOf<T>( pred: Predicate<T>,): & Predicate<Readonly<T>> & WithMetadata<IsReadonlyOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is Readonly<T> => pred(x), { name: "isReadonlyOf", args: [pred] }, ) as & Predicate<Readonly<T>> & WithMetadata<IsReadonlyOfMetadata>;}
type IsReadonlyOfMetadata = { name: "isReadonlyOf"; args: Parameters<typeof isReadonlyOf>;};
/** * Return an `Readonly` un-annotated type predicate function that returns `true` if the type of `x` is `T`. * * **This is unstable and may be removed in the future.** * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.UnwrapReadonlyOf(is.ReadonlyOf(is.TupleOf([is.String, is.Number]))); * const a: unknown = ["a", 1]; * if (isMyType(a)) { * // a is narrowed to [string, number] * const _: [string, number] = a; * } * ``` */export function isUnwrapReadonlyOf<P extends Predicate<unknown>>( pred: P,): UnwrapReadonlyOf<P> { if (!isReadonly(pred)) return pred as UnwrapReadonlyOf<P>; const { args } = getPredicateFactoryMetadata(pred); return args[0] as UnwrapReadonlyOf<P>;}
type UnwrapReadonlyOf<T> = T extends Predicate<infer U> & WithMetadata<IsReadonlyOfMetadata> ? Predicate<Writable<U>> : T extends Predicate<unknown> ? T : never;
/** * Return a type predicate function that returns `true` if the type of `x` is `T[]`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ArrayOf(is.String); * const a: unknown = ["a", "b", "c"]; * if (isMyType(a)) { * // a is narrowed to string[] * const _: string[] = a; * } * ``` */export function isArrayOf<T>( pred: Predicate<T>,): Predicate<T[]> & WithMetadata<IsArrayOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is T[] => isArray(x) && x.every(pred), { name: "isArrayOf", args: [pred] }, );}
type IsArrayOfMetadata = { name: "isArrayOf"; args: Parameters<typeof isArrayOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is `Set<T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.SetOf(is.String); * const a: unknown = new Set(["a", "b", "c"]); * if (isMyType(a)) { * // a is narrowed to Set<string> * const _: Set<string> = a; * } * ``` */export function isSetOf<T>( pred: Predicate<T>,): Predicate<Set<T>> & WithMetadata<IsSetOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is Set<T> => { if (!isSet(x)) return false; for (const v of x.values()) { if (!pred(v)) return false; } return true; }, { name: "isSetOf", args: [pred] }, );}
type IsSetOfMetadata = { name: "isSetOf"; args: Parameters<typeof isSetOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is `TupleOf<T>` or `TupleOf<T, E>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.TupleOf([is.Number, is.String, is.Boolean]); * const a: unknown = [0, "a", true]; * if (isMyType(a)) { * // a is narrowed to [number, string, boolean] * const _: [number, string, boolean] = a; * } * ``` * * With `predElse`: * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.TupleOf( * [is.Number, is.String, is.Boolean], * is.ArrayOf(is.Number), * ); * const a: unknown = [0, "a", true, 0, 1, 2]; * if (isMyType(a)) { * // a is narrowed to [number, string, boolean, ...number[]] * const _: [number, string, boolean, ...number[]] = a; * } * ``` * * Depending on the version of TypeScript and how values are provided, it may be necessary to add `as const` to the array * used as `predTup`. If a type error occurs, try adding `as const` as follows: * * ```ts * import { is } from "@core/unknownutil"; * * const predTup = [is.Number, is.String, is.Boolean] as const; * const isMyType = is.TupleOf(predTup); * const a: unknown = [0, "a", true]; * if (isMyType(a)) { * // a is narrowed to [number, string, boolean] * const _: [number, string, boolean] = a; * } * ``` */export function isTupleOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]],>( predTup: T,): Predicate<TupleOf<T>> & WithMetadata<IsTupleOfMetadata>;export function isTupleOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]], E extends Predicate<unknown[]>,>( predTup: T, predElse: E,): & Predicate<[...TupleOf<T>, ...PredicateType<E>]> & WithMetadata<IsTupleOfMetadata>;export function isTupleOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]], E extends Predicate<unknown[]>,>( predTup: T, predElse?: E,): & Predicate<TupleOf<T> | [...TupleOf<T>, ...PredicateType<E>]> & WithMetadata<IsTupleOfMetadata> { if (!predElse) { return setPredicateFactoryMetadata( (x: unknown): x is TupleOf<T> => { if (!isArray(x) || x.length !== predTup.length) { return false; } return predTup.every((pred, i) => pred(x[i])); }, { name: "isTupleOf", args: [predTup] }, ); } else { return setPredicateFactoryMetadata( (x: unknown): x is [...TupleOf<T>, ...PredicateType<E>] => { if (!isArray(x) || x.length < predTup.length) { return false; } const head = x.slice(0, predTup.length); const tail = x.slice(predTup.length); return predTup.every((pred, i) => pred(head[i])) && predElse(tail); }, { name: "isTupleOf", args: [predTup, predElse] }, ); }}
type TupleOf<T> = { -readonly [P in keyof T]: T[P] extends Predicate<infer U> ? U : never;};
type IsTupleOfMetadata = { name: "isTupleOf"; args: [Parameters<typeof isTupleOf>[0], Parameters<typeof isTupleOf>[1]?];};
/** * Return a type predicate function that returns `true` if the type of `x` is `ParametersOf<T>` or `ParametersOf<T, E>`. * * This is similar to `TupleOf<T>` or `TupleOf<T, E>`, but if `is.OptionalOf()` 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. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ParametersOf([ * is.Number, * is.OptionalOf(is.String), * is.Boolean, * is.OptionalOf(is.Number), * is.OptionalOf(is.String), * is.OptionalOf(is.Boolean), * ] as const); * const a: unknown = [0, undefined, "a"]; * if (isMyType(a)) { * // a is narrowed to [number, string | undefined, boolean, number?, string?, boolean?] * const _: [number, string | undefined, boolean, number?, string?, boolean?] = a; * } * ``` * * With `predElse`: * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ParametersOf( * [ * is.Number, * is.OptionalOf(is.String), * is.OptionalOf(is.Boolean), * ] as const, * is.ArrayOf(is.Number), * ); * const a: unknown = [0, "a", true, 0, 1, 2]; * if (isMyType(a)) { * // a is narrowed to [number, string?, boolean?, ...number[]] * const _: [number, string?, boolean?, ...number[]] = a; * } * ``` * * Depending on the version of TypeScript and how values are provided, it may be necessary to add `as const` to the array * used as `predTup`. If a type error occurs, try adding `as const` as follows: * * ```ts * import { is } from "@core/unknownutil"; * * const predTup = [is.Number, is.String, is.OptionalOf(is.Boolean)] as const; * const isMyType = is.ParametersOf(predTup); * const a: unknown = [0, "a"]; * if (isMyType(a)) { * // a is narrowed to [number, string, boolean?] * const _: [number, string, boolean?] = a; * } * ``` */export function isParametersOf< T extends readonly [...Predicate<unknown>[]],>( predTup: T,): Predicate<ParametersOf<T>> & WithMetadata<IsParametersOfMetadata>;export function isParametersOf< T extends readonly [...Predicate<unknown>[]], E extends Predicate<unknown[]>,>( predTup: T, predElse: E,): & Predicate<[...ParametersOf<T>, ...PredicateType<E>]> & WithMetadata<IsParametersOfMetadata>;export function isParametersOf< T extends readonly [...Predicate<unknown>[]], E extends Predicate<unknown[]>,>( predTup: T, predElse?: E,): & Predicate<ParametersOf<T> | [...ParametersOf<T>, ...PredicateType<E>]> & WithMetadata<IsParametersOfMetadata> { const requiresLength = 1 + predTup.findLastIndex((pred) => !isOptional(pred)); if (!predElse) { return setPredicateFactoryMetadata( (x: unknown): x is ParametersOf<T> => { if ( !isArray(x) || x.length < requiresLength || x.length > predTup.length ) { return false; } return predTup.every((pred, i) => pred(x[i])); }, { name: "isParametersOf", args: [predTup] }, ); } else { return setPredicateFactoryMetadata( (x: unknown): x is [...ParametersOf<T>, ...PredicateType<E>] => { if (!isArray(x) || x.length < requiresLength) { return false; } const head = x.slice(0, predTup.length); const tail = x.slice(predTup.length); return predTup.every((pred, i) => pred(head[i])) && predElse(tail); }, { name: "isParametersOf", args: [predTup, predElse] }, ); }}
type ParametersOf<T> = T extends readonly [] ? [] : T extends readonly [...infer P, infer R] // Tuple of predicates ? P extends Predicate<unknown>[] ? R extends Predicate<unknown> & WithMetadata<IsOptionalOfMetadata> // Last parameter is optional ? [...ParametersOf<P>, PredicateType<R>?] // Last parameter is NOT optional : [...ParametersOf<P>, PredicateType<R>] : never // Array of predicates : TupleOf<T>;
type IsParametersOfMetadata = { name: "isParametersOf"; args: [ Parameters<typeof isParametersOf>[0], Parameters<typeof isParametersOf>[1]?, ];};
/** * Return a type predicate function that returns `true` if the type of `x` is `Readonly<TupleOf<T>>`. * * @deprecated Use `is.ReadonlyOf(is.TupleOf(...))` instead. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ReadonlyTupleOf([is.Number, is.String, is.Boolean]); * const a: unknown = [0, "a", true]; * if (isMyType(a)) { * // a is narrowed to readonly [number, string, boolean] * const _: readonly [number, string, boolean] = a; * } * ``` * * With `predElse`: * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ReadonlyTupleOf( * [is.Number, is.String, is.Boolean], * is.ArrayOf(is.Number), * ); * const a: unknown = [0, "a", true, 0, 1, 2]; * if (isMyType(a)) { * // a is narrowed to readonly [number, string, boolean, ...number[]] * const _: readonly [number, string, boolean, ...number[]] = a; * } * ``` * * Depending on the version of TypeScript and how values are provided, it may be necessary to add `as const` to the array * used as `predTup`. If a type error occurs, try adding `as const` as follows: * * ```ts * import { is } from "@core/unknownutil"; * * const predTup = [is.Number, is.String, is.Boolean] as const; * const isMyType = is.ReadonlyTupleOf(predTup); * const a: unknown = [0, "a", true]; * if (isMyType(a)) { * // a is narrowed to readonly [number, string, boolean] * const _: readonly [number, string, boolean] = a; * } * ``` */export function isReadonlyTupleOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]],>( predTup: T,): Predicate<Readonly<TupleOf<T>>> & WithMetadata<IsReadonlyOfMetadata>;export function isReadonlyTupleOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]], E extends Predicate<unknown[]>,>( predTup: T, predElse: E,): & Predicate<Readonly<[...TupleOf<T>, ...PredicateType<E>]>> & WithMetadata<IsReadonlyOfMetadata>;export function isReadonlyTupleOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]], E extends Predicate<unknown[]>,>( predTup: T, predElse?: E,): & Predicate< | Readonly<TupleOf<T>> | Readonly<[...TupleOf<T>, ...PredicateType<E>]> > & WithMetadata<IsReadonlyOfMetadata> { if (!predElse) { return isReadonlyOf(isTupleOf(predTup)); } else { return isReadonlyOf(isTupleOf(predTup, predElse)); }}
/** * Return a type predicate function that returns `true` if the type of `x` is `UniformTupleOf<T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.UniformTupleOf(5); * const a: unknown = [0, 1, 2, 3, 4]; * if (isMyType(a)) { * // a is narrowed to [unknown, unknown, unknown, unknown, unknown] * const _: [unknown, unknown, unknown, unknown, unknown] = a; * } * ``` * * With predicate function: * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.UniformTupleOf(5, is.Number); * const a: unknown = [0, 1, 2, 3, 4]; * if (isMyType(a)) { * // a is narrowed to [number, number, number, number, number] * const _: [number, number, number, number, number] = a; * } * ``` */export function isUniformTupleOf<T, N extends number>( n: N, pred: Predicate<T> = isAny,): Predicate<UniformTupleOf<T, N>> & WithMetadata<IsUniformTupleOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is UniformTupleOf<T, N> => { if (!isArray(x) || x.length !== n) { return false; } return x.every((v) => pred(v)); }, { name: "isUniformTupleOf", args: [n, pred] }, );}
// https://stackoverflow.com/a/71700658/1273406type UniformTupleOf< T, N extends number, R extends readonly T[] = [],> = R["length"] extends N ? R : UniformTupleOf<T, N, [T, ...R]>;
type IsUniformTupleOfMetadata = { name: "isUniformTupleOf"; args: Parameters<typeof isUniformTupleOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is `Readonly<UniformTupleOf<T>>`. * * @deprecated Use `is.ReadonlyOf(is.UniformTupleOf(...))` instead. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ReadonlyUniformTupleOf(5); * const a: unknown = [0, 1, 2, 3, 4]; * if (isMyType(a)) { * // a is narrowed to readonly [unknown, unknown, unknown, unknown, unknown] * const _: readonly [unknown, unknown, unknown, unknown, unknown] = a; * } * ``` * * With predicate function: * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ReadonlyUniformTupleOf(5, is.Number); * const a: unknown = [0, 1, 2, 3, 4]; * if (isMyType(a)) { * // a is narrowed to readonly [number, number, number, number, number] * const _: readonly [number, number, number, number, number] = a; * } * ``` */export function isReadonlyUniformTupleOf<T, N extends number>( n: N, pred: Predicate<T> = isAny,): & Predicate<Readonly<UniformTupleOf<T, N>>> & WithMetadata<IsReadonlyOfMetadata> { return isReadonlyOf(isUniformTupleOf(n, pred));}
/** * Return a type predicate function that returns `true` if the type of `x` is an Object instance that satisfies `Record<K, T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * Note that this function check if the `x` is an instance of `Object`. * Use `isRecordOf` instead if you want to check if the `x` satisfies the `Record<K, T>` type. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.RecordObjectOf(is.Number); * const a: unknown = {"a": 0, "b": 1}; * if (isMyType(a)) { * // a is narrowed to Record<PropertyKey, number> * const _: Record<PropertyKey, number> = a; * } * ``` * * With predicate function for keys: * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.RecordObjectOf(is.Number, is.String); * const a: unknown = {"a": 0, "b": 1}; * if (isMyType(a)) { * // a is narrowed to Record<string, number> * const _: Record<string, number> = a; * } * ``` */export function isRecordObjectOf<T, K extends PropertyKey = PropertyKey>( pred: Predicate<T>, predKey?: Predicate<K>,): Predicate<Record<K, T>> & WithMetadata<IsRecordObjectOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is Record<K, T> => { if (!isRecordObject(x)) return false; for (const k in x) { if (!pred(x[k])) return false; if (predKey && !predKey(k)) return false; } return true; }, { name: "isRecordObjectOf", args: [pred, predKey] }, );}
type IsRecordObjectOfMetadata = { name: "isRecordObjectOf"; args: Parameters<typeof isRecordObjectOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` satisfies `Record<K, T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.RecordOf(is.Number); * const a: unknown = {"a": 0, "b": 1}; * if (isMyType(a)) { * // a is narrowed to Record<PropertyKey, number> * const _: Record<PropertyKey, number> = a; * } * ``` * * With predicate function for keys: * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.RecordOf(is.Number, is.String); * const a: unknown = {"a": 0, "b": 1}; * if (isMyType(a)) { * // a is narrowed to Record<string, number> * const _: Record<string, number> = a; * } * ``` */export function isRecordOf<T, K extends PropertyKey = PropertyKey>( pred: Predicate<T>, predKey?: Predicate<K>,): Predicate<Record<K, T>> & WithMetadata<IsRecordOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is Record<K, T> => { if (!isRecord(x)) return false; for (const k in x) { if (!pred(x[k])) return false; if (predKey && !predKey(k)) return false; } return true; }, { name: "isRecordOf", args: [pred, predKey] }, );}
type IsRecordOfMetadata = { name: "isRecordOf"; args: Parameters<typeof isRecordOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` satisfies `Record<K, T>`. * * @deprecated Use `is.RecordOf()` instead */export function isRecordLikeOf<T, K extends PropertyKey = PropertyKey>( pred: Predicate<T>, predKey?: Predicate<K>,): Predicate<Record<K, T>> & WithMetadata<IsRecordLikeOfMetadata> { return setPredicateFactoryMetadata(isRecordOf(pred, predKey), { name: "isRecordLikeOf", args: [pred, predKey], });}
type IsRecordLikeOfMetadata = { name: "isRecordLikeOf"; args: Parameters<typeof isRecordLikeOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is `Map<K, T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.MapOf(is.Number); * const a: unknown = new Map([["a", 0], ["b", 1]]); * if (isMyType(a)) { * // a is narrowed to Map<unknown, number> * const _: Map<unknown, number> = a; * } * ``` * * With predicate function for keys: * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.MapOf(is.Number, is.String); * const a: unknown = new Map([["a", 0], ["b", 1]]); * if (isMyType(a)) { * // a is narrowed to Map<string, number> * const _: Map<string, number> = a; * } * ``` */export function isMapOf<T, K>( pred: Predicate<T>, predKey?: Predicate<K>,): Predicate<Map<K, T>> & WithMetadata<IsMapOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is Map<K, T> => { if (!isMap(x)) return false; for (const entry of x.entries()) { const [k, v] = entry; if (!pred(v)) return false; if (predKey && !predKey(k)) return false; } return true; }, { name: "isMapOf", args: [pred, predKey] }, );}
type IsMapOfMetadata = { name: "isMapOf"; args: Parameters<typeof isMapOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is `ObjectOf<T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * If `is.OptionalOf()` is specified in the predicate function, the property becomes optional. * * The number of keys of `x` must be greater than or equal to the number of keys of `predObj`. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.ObjectOf({ * a: is.Number, * b: is.String, * c: is.OptionalOf(is.Boolean), * }); * const a: unknown = { a: 0, b: "a", other: "other" }; * if (isMyType(a)) { * // "other" key in `a` is ignored because of `options.strict` is `false`. * // a is narrowed to { a: number; b: string; c?: boolean | undefined } * const _: { a: number; b: string; c?: boolean | undefined } = a; * } * ``` */export function isObjectOf< T extends Record<PropertyKey, Predicate<unknown>>,>( predObj: T,): Predicate<ObjectOf<T>> & WithMetadata<IsObjectOfMetadata>;/** * @deprecated The `option.strict` is deprecated. Use `isStrictOf()` instead. */export function isObjectOf< T extends Record<PropertyKey, Predicate<unknown>>,>( predObj: T, options: { strict?: boolean },): Predicate<ObjectOf<T>> & WithMetadata<IsObjectOfMetadata>;export function isObjectOf< T extends Record<PropertyKey, Predicate<unknown>>,>( predObj: T, options?: { strict?: boolean },): Predicate<ObjectOf<T>> & WithMetadata<IsObjectOfMetadata> { if (options?.strict) { // deno-lint-ignore no-explicit-any return isStrictOf(isObjectOf(predObj)) as any; } return setPredicateFactoryMetadata( (x: unknown): x is ObjectOf<T> => { if ( x == null || typeof x !== "object" && typeof x !== "function" || Array.isArray(x) ) return false; // Check each values for (const k in predObj) { if (!predObj[k]((x as T)[k])) return false; } return true; }, { name: "isObjectOf", args: [predObj] }, );}
type WithOptional = | WithMetadata<GetMetadata<ReturnType<typeof isOptionalOf>>> | { optional: true }; // For backward compatibility
type ObjectOf<T extends Record<PropertyKey, Predicate<unknown>>> = FlatType< // Non optional & { [K in keyof T as T[K] extends WithOptional ? never : K]: T[K] extends Predicate<infer U> ? U : never; } // Optional & { [K in keyof T as T[K] extends WithOptional ? K : never]?: T[K] extends Predicate<infer U> ? U : never; }>;
type IsObjectOfMetadata = { name: "isObjectOf"; args: [Parameters<typeof isObjectOf>[0]];};
/** * Return a type predicate function that returns `true` if the type of `x` is strictly follow the `ObjectOf<T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * If `is.OptionalOf()` is specified in the predicate function, the property becomes optional. * * The number of keys of `x` must be equal to the number of non optional keys of `predObj`. This is equivalent to * the deprecated `options.strict` in `isObjectOf()`. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.StrictOf(is.ObjectOf({ * a: is.Number, * b: is.String, * c: is.OptionalOf(is.Boolean), * })); * const a: unknown = { a: 0, b: "a", other: "other" }; * if (isMyType(a)) { * // This block will not be executed because of "other" key in `a`. * } * ``` */export function isStrictOf<T extends Record<PropertyKey, unknown>>( pred: & Predicate<T> & WithMetadata<IsObjectOfMetadata>,): & Predicate<T> & WithMetadata<IsStrictOfMetadata> { const { args } = getPredicateFactoryMetadata(pred); const s = new Set(Object.keys(args[0])); return setPredicateFactoryMetadata( (x: unknown): x is T => { if (!pred(x)) return false; // deno-lint-ignore no-explicit-any const ks = Object.keys(x as any); return ks.length <= s.size && ks.every((k) => s.has(k)); }, { name: "isStrictOf", args: [pred] }, );}
type IsStrictOfMetadata = { name: "isStrictOf"; args: Parameters<typeof isStrictOf>;};
/** * Return `true` if the type of `x` is instance of `ctor`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.InstanceOf(Date); * const a: unknown = new Date(); * if (isMyType(a)) { * // a is narrowed to Date * const _: Date = a; * } * ``` */// deno-lint-ignore no-explicit-anyexport function isInstanceOf<T extends new (...args: any) => unknown>( ctor: T,): Predicate<InstanceType<T>> & WithMetadata<IsInstanceOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is InstanceType<T> => x instanceof ctor, { name: "isInstanceOf", args: [ctor] }, );}
type IsInstanceOfMetadata = { name: "isInstanceOf"; args: Parameters<typeof isInstanceOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is a literal type of `pred`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.LiteralOf("hello"); * const a: unknown = "hello"; * if (isMyType(a)) { * // a is narrowed to "hello" * const _: "hello" = a; * } * ``` */export function isLiteralOf<T extends Primitive>( literal: T,): Predicate<T> & WithMetadata<IsLiteralOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is T => x === literal, { name: "isLiteralOf", args: [literal] }, );}
type IsLiteralOfMetadata = { name: "isLiteralOf"; args: Parameters<typeof isLiteralOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is one of literal type in `preds`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.LiteralOneOf(["hello", "world"] as const); * const a: unknown = "hello"; * if (isMyType(a)) { * // a is narrowed to "hello" | "world" * const _: "hello" | "world" = a; * } * ``` */export function isLiteralOneOf<T extends readonly Primitive[]>( literals: T,): Predicate<T[number]> & WithMetadata<IsLiteralOneOfMetadata> { const s = new Set(literals); return setPredicateFactoryMetadata( (x: unknown): x is T[number] => s.has(x as T[number]), { name: "isLiteralOneOf", args: [literals] }, );}
type IsLiteralOneOfMetadata = { name: "isLiteralOneOf"; args: Parameters<typeof isLiteralOneOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is `UnionOf<T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.UnionOf([is.Number, is.String, is.Boolean]); * const a: unknown = 0; * if (isMyType(a)) { * // a is narrowed to number | string | boolean * const _: number | string | boolean = a; * } * ``` * * Depending on the version of TypeScript and how values are provided, it may be necessary to add `as const` to the array * used as `preds`. If a type error occurs, try adding `as const` as follows: * * ```ts * import { is } from "@core/unknownutil"; * * const preds = [is.Number, is.String, is.Boolean] as const; * const isMyType = is.UnionOf(preds); * const a: unknown = 0; * if (isMyType(a)) { * // a is narrowed to number | string | boolean * const _: number | string | boolean = a; * } * ``` */export function isUnionOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]],>( preds: T,): Predicate<UnionOf<T>> & WithMetadata<IsUnionOfMetadata> { return setPredicateFactoryMetadata( (x: unknown): x is UnionOf<T> => preds.some((pred) => pred(x)), { name: "isUnionOf", args: [preds] }, );}
type UnionOf<T> = T extends readonly [Predicate<infer U>, ...infer R] ? U | UnionOf<R> : never;
type IsUnionOfMetadata = { name: "isUnionOf"; args: Parameters<typeof isUnionOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is `IntersectionOf<T>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```ts * import { is } from "@core/unknownutil"; * * const isMyType = is.IntersectionOf([ * is.ObjectOf({ a: is.Number }), * is.ObjectOf({ b: is.String }), * ]); * const a: unknown = { a: 0, b: "a" }; * if (isMyType(a)) { * // a is narrowed to { a: number } & { b: string } * const _: { a: number } & { b: string } = a; * } * ``` * * Depending on the version of TypeScript and how values are provided, it may be necessary to add `as const` to the array * used as `preds`. If a type error occurs, try adding `as const` as follows: * * ```ts * import { is } from "@core/unknownutil"; * * const preds = [ * is.ObjectOf({ a: is.Number }), * is.ObjectOf({ b: is.String }), * ] as const * const isMyType = is.IntersectionOf(preds); * const a: unknown = { a: 0, b: "a" }; * if (isMyType(a)) { * // a is narrowed to { a: number } & { b: string } * const _: { a: number } & { b: string } = a; * } * ``` */export function isIntersectionOf< T extends readonly [ Predicate<unknown> & WithMetadata<IsObjectOfMetadata>, ...(Predicate<unknown> & WithMetadata<IsObjectOfMetadata>)[], ],>( preds: T,): Predicate<IntersectionOf<T>> & WithMetadata<IsObjectOfMetadata>;export function isIntersectionOf< T extends readonly [Predicate<unknown>],>( preds: T,): T[0];export function isIntersectionOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]],>( preds: T,): Predicate<IntersectionOf<T>> & WithMetadata<IsIntersectionOfMetadata>;export function isIntersectionOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]],>( preds: T,): | Predicate<unknown> | Predicate<IntersectionOf<T>> & WithMetadata<IsObjectOfMetadata | IsIntersectionOfMetadata> { const predObj = {}; const restPreds = preds.filter((pred) => { const meta = getMetadata(pred); if ((meta as IsObjectOfMetadata)?.name !== "isObjectOf") { return true; } Object.assign(predObj, (meta as IsObjectOfMetadata).args[0]); }); if (restPreds.length < preds.length) { restPreds.push(isObjectOf(predObj)); } if (restPreds.length === 1) { return restPreds[0]; } return setPredicateFactoryMetadata( (x: unknown): x is IntersectionOf<T> => restPreds.every((pred) => pred(x)), { name: "isIntersectionOf", args: [preds] }, );}
type IntersectionOf<T> = TupleToIntersection<TupleOf<T>>;
type IsIntersectionOfMetadata = { name: "isIntersectionOf"; args: Parameters<typeof isIntersectionOf>;};
/** * Return a type predicate function that returns `true` if the type of `x` is `Required<ObjectOf<T>>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript * import { is } from "@core/unknownutil"; * * const isMyType = is.RequiredOf(is.ObjectOf({ * a: is.Number, * b: is.UnionOf([is.String, is.Undefined]), * c: is.OptionalOf(is.Boolean), * })); * const a: unknown = { a: 0, b: "b", c: true, other: "other" }; * if (isMyType(a)) { * // 'a' is narrowed to { a: number; b: string | undefined; c: boolean } * const _: { a: number; b: string | undefined; c: boolean } = a; * } * ``` */export function isRequiredOf< T extends Record<PropertyKey, unknown>,>( pred: Predicate<T> & WithMetadata<IsObjectOfMetadata>,): & Predicate<FlatType<Required<T>>> & WithMetadata<IsObjectOfMetadata> { const { args } = getPredicateFactoryMetadata(pred); const predObj = Object.fromEntries( Object.entries(args[0]).map(([k, v]) => [k, isUnwrapOptionalOf(v)]), ); return isObjectOf(predObj) as & Predicate<FlatType<Required<T>>> & WithMetadata<IsObjectOfMetadata>;}
/** * Return a type predicate function that returns `true` if the type of `x` is `Partial<ObjectOf<T>>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript * import { is } from "@core/unknownutil"; * * const isMyType = is.PartialOf(is.ObjectOf({ * a: is.Number, * b: is.UnionOf([is.String, is.Undefined]), * c: is.OptionalOf(is.Boolean), * })); * const a: unknown = { a: undefined, other: "other" }; * if (isMyType(a)) { * // The "other" key in `a` is ignored. * // 'a' is narrowed to { a?: number | undefined; b?: string | undefined; c?: boolean | undefined } * const _: { a?: number | undefined; b?: string | undefined; c?: boolean | undefined } = a; * } * ``` */export function isPartialOf< T extends Record<PropertyKey, unknown>,>( pred: Predicate<T> & WithMetadata<IsObjectOfMetadata>,): & Predicate<FlatType<Partial<T>>> & WithMetadata<IsObjectOfMetadata> { const { args } = getPredicateFactoryMetadata(pred); const predObj = Object.fromEntries( Object.entries(args[0]).map(([k, v]) => [k, isOptionalOf(v)]), ); return isObjectOf(predObj) as & Predicate<FlatType<Partial<T>>> & WithMetadata<IsObjectOfMetadata>;}
/** * Return a type predicate function that returns `true` if the type of `x` is `Pick<ObjectOf<T>, K>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript * import { is } from "@core/unknownutil"; * * const isMyType = is.PickOf(is.ObjectOf({ * a: is.Number, * b: is.String, * c: is.OptionalOf(is.Boolean), * }), ["a", "c"]); * const a: unknown = { a: 0, b: "a", other: "other" }; * if (isMyType(a)) { * // The "b" and "other" key in `a` is ignored. * // 'a' is narrowed to { a: number; c?: boolean | undefined } * const _: { a: number; c?: boolean | undefined } = a; * } * ``` */export function isPickOf< T extends Record<PropertyKey, unknown>, K extends keyof T,>( pred: Predicate<T> & WithMetadata<IsObjectOfMetadata>, keys: K[],): & Predicate<FlatType<Pick<T, K>>> & WithMetadata<IsObjectOfMetadata> { const s = new Set(keys); const { args } = getPredicateFactoryMetadata(pred); const predObj = Object.fromEntries( Object.entries(args[0]).filter(([k]) => s.has(k as K)), ); return isObjectOf(predObj) as & Predicate<FlatType<Pick<T, K>>> & WithMetadata<IsObjectOfMetadata>;}
/** * Return a type predicate function that returns `true` if the type of `x` is `Omit<ObjectOf<T>, K>`. * * To enhance performance, users are advised to cache the return value of this function and mitigate the creation cost. * * ```typescript * import { is } from "@core/unknownutil"; * * const isMyType = is.OmitOf(is.ObjectOf({ * a: is.Number, * b: is.String, * c: is.OptionalOf(is.Boolean), * }), ["a", "c"]); * const a: unknown = { a: 0, b: "a", other: "other" }; * if (isMyType(a)) { * // The "a", "c", and "other" key in `a` is ignored. * // 'a' is narrowed to { b: string } * const _: { b: string } = a; * } * ``` */export function isOmitOf< T extends Record<PropertyKey, unknown>, K extends keyof T,>( pred: Predicate<T> & WithMetadata<IsObjectOfMetadata>, keys: K[],): & Predicate<FlatType<Omit<T, K>>> & WithMetadata<IsObjectOfMetadata> { const s = new Set(keys); const { args } = getPredicateFactoryMetadata(pred); const predObj = Object.fromEntries( Object.entries(args[0]).filter(([k]) => !s.has(k as K)), ); return isObjectOf(predObj) as & Predicate<FlatType<Omit<T, K>>> & WithMetadata<IsObjectOfMetadata>;}
/** * Return a type predicate function that returns `true` if the type of `x` is `UnionOf<T>`. * * @deprecated Use `isUnionOf` instead. */export function isOneOf< T extends readonly [Predicate<unknown>, ...Predicate<unknown>[]],>( preds: T,): Predicate<OneOf<T>> { return isUnionOf(preds);}
type OneOf<T> = T extends readonly [Predicate<infer U>, ...infer R] ? U | OneOf<R> : never;
/** * Return a type predicate function that returns `true` if the type of `x` is `IntersectionOf<T>`. * * @deprecated Use `isIntersectionOf` instead. */export function isAllOf< T extends readonly [ Predicate<unknown> & WithMetadata<IsObjectOfMetadata>, ...(Predicate<unknown> & WithMetadata<IsObjectOfMetadata>)[], ],>( preds: T,): Predicate<AllOf<T>> { return isIntersectionOf(preds);}
type AllOf<T> = IntersectionOf<T>;
export const is = { AllOf: isAllOf, Any: isAny, Array: isArray, ArrayOf: isArrayOf, AsyncFunction: isAsyncFunction, BigInt: isBigInt, Boolean: isBoolean, Function: isFunction, InstanceOf: isInstanceOf, IntersectionOf: isIntersectionOf, LiteralOf: isLiteralOf, LiteralOneOf: isLiteralOneOf, Map: isMap, MapOf: isMapOf, Null: isNull, Nullish: isNullish, Number: isNumber, ObjectOf: isObjectOf, OmitOf: isOmitOf, OneOf: isOneOf, Optional: isOptional, OptionalOf: isOptionalOf, ParametersOf: isParametersOf, PartialOf: isPartialOf, PickOf: isPickOf, Primitive: isPrimitive, Readonly: isReadonly, ReadonlyOf: isReadonlyOf, ReadonlyTupleOf: isReadonlyTupleOf, ReadonlyUniformTupleOf: isReadonlyUniformTupleOf, Record: isRecord, RecordLike: isRecordLike, RecordLikeOf: isRecordLikeOf, RecordObject: isRecordObject, RecordObjectOf: isRecordObjectOf, RecordOf: isRecordOf, RequiredOf: isRequiredOf, Set: isSet, SetOf: isSetOf, StrictOf: isStrictOf, String: isString, Symbol: isSymbol, SyncFunction: isSyncFunction, TupleOf: isTupleOf, Undefined: isUndefined, UniformTupleOf: isUniformTupleOf, UnionOf: isUnionOf, Unknown: isUnknown, UnwrapOptionalOf: isUnwrapOptionalOf, UnwrapReadonlyOf: isUnwrapReadonlyOf,};