generic-type-guard
Version:
Generic type guards for TypeScript
543 lines (486 loc) • 16.9 kB
TypeScript
/**
* Asserts that a guard is successful.
*
* This may not work properly in ECMAScript environments that don't fully support ES6. If this is your environment then
* you should do this check manually and throw your own error.
*
* @throws AssertionError if the guard returns false.
* @public
*/
export declare const assert: <T, Guard extends PartialTypeGuard<T, T>>(value: T, guard: Guard, message?: string) => asserts value is GuardedType<Guard>;
/**
* Indicates there was an error validating a typeguard.
*
* @public
*/
export declare class AssertionError extends RangeError {
value: unknown;
constructor(value: unknown, message?: string);
}
/**
* Helper to string many different typeguards together into something larger.
*
* @param guards - A list of partial typeguards to string together.
*
* @public
*/
export declare const combine: {
<A, B extends A, C extends B>(g1: PartialTypeGuard<A, B>, g2: PartialTypeGuard<B, C>): PartialTypeGuard<A, C>;
<A, B extends A, C extends B, D extends C>(g1: PartialTypeGuard<A, B>, g2: PartialTypeGuard<B, C>, g3: PartialTypeGuard<C, D>): PartialTypeGuard<A, D>;
<A, B extends A, C extends B, D extends C, E extends D>(g1: PartialTypeGuard<A, B>, g2: PartialTypeGuard<B, C>, g3: PartialTypeGuard<C, D>, g4: PartialTypeGuard<D, E>): PartialTypeGuard<A, E>;
<A, B extends A, C extends B, D extends C, E extends D, F extends E>(g1: PartialTypeGuard<A, B>, g2: PartialTypeGuard<B, C>, g3: PartialTypeGuard<C, D>, g4: PartialTypeGuard<D, E>, g5: PartialTypeGuard<D, E>): PartialTypeGuard<A, F>;
};
/**
* Helper to diff types.
* @public
*/
export declare type Diff<T, U> = T extends U ? never : T;
/**
* Extracts the type that is being guarded for from a type guard.
*
* @public
*/
export declare type GuardedType<T extends PartialTypeGuard<any, unknown>> = T extends PartialTypeGuard<any, infer U> ? U : never;
/**
* Validates that a given object has a numeric index signature.
*
* @param enforce - Whether to enforce that there is at least one property already set. Be careful setting this to
* false, you will get some unexpected outputs, for instance objects will have a numeric index signature.
*
* @public
*/
export declare const hasNumericIndexSignature: <V>(value: TypeGuard<V>, enforce?: boolean) => PartialTypeGuard<object, Record<number, V>>;
/**
* Validate that a given object only has the given properties
*
* @param props - A MappedTypeGuard of the object to be validated.
*
* @public
*/
export declare const hasOnlyProperties: <V extends object>(props: MappedTypeGuard<V>) => PartialTypeGuard<object, V>;
/**
* Validate that a given object has all the given optional properties
*
* @param props - a MappedGuard of the object to be validated, i.e. an object that has the same properties as the
* object being validated whose types are TypeGuards for the matching type on the original property.
*
* @public
*/
export declare const hasOptionalProperties: <V extends object>(props: MappedTypeGuard<V>) => PartialTypeGuard<object, Partial<V>>;
/**
* Validates that a given object has an optional property of a given type.
*
* @public
*/
export declare const hasOptionalProperty: <K extends string, V>(property: K, value: TypeGuard<V>) => PartialTypeGuard<object, Partial<Record<K, V>>>;
/**
* Validate that a given object has all the given properties
*
* @param props - a MappedGuard of the object to be validated, i.e. an object that has the same properties as the
* object being validated whose types are TypeGuards for the matching type on the original property.
*
* @public
*/
export declare const hasProperties: <V extends object>(props: MappedTypeGuard<V>) => PartialTypeGuard<object, V>;
/**
* Validates that a given object has a property of a given type.
*
* @public
*/
export declare const hasProperty: <K extends string, V>(property: K, value: TypeGuard<V>) => PartialTypeGuard<object, Record<K, V>>;
/**
* Validates that a given object has a string index signature.
*
* @param enforce - Whether to enforce that there is at least one property already set. Be careful setting this to
* false, you will get some unexpected outputs, for instance arrays will have a string index signature.
*
* @public
*/
export declare const hasStringIndexSignature: <V>(value: TypeGuard<V>, enforce?: boolean) => PartialTypeGuard<object, Record<string, V>>;
/**
* Fluent Builder pattern for creating guards for interface types.
*
* @public
*/
export declare interface InterfaceBuilder<T extends object> {
/**
* Finalise and return the type guard which has been built.
*/
get: () => TypeGuard<T>;
/**
* Add a free-form type guard to this interface as a union.
*/
with: <V extends object>(ptv: PartialTypeGuard<object, V>) => InterfaceBuilder<T & V>;
/**
* Add a single property to the interface.
*
* @param key - The string key of the property.
* @param ptv - The type guard for this property.
*/
withProperty: <K extends string, V>(key: K, ptv: TypeGuard<V>) => InterfaceBuilder<T & Record<K, V>>;
/**
* Add a single optional property to the interface.
*
* @param key - The string key of the property.
* @param ptv - The type guard for this property.
*/
withOptionalProperty: <K extends string, V>(key: K, ptv: TypeGuard<V>) => InterfaceBuilder<T & Partial<Record<K, V>>>;
/**
* Add a string index signature to the interface.
*
* @param value - The type guard for values accessed by the index signature.
* @param enforce - Whether to enforce that there is at least one property already set. Be careful setting this to
* false, you will get some unexpected outputs, for instance arrays will have a string index signature.
*/
withStringIndexSignature: <V>(value: TypeGuard<V>, enforce?: boolean) => InterfaceBuilder<T & Record<string, V>>;
/**
* Add a numeric index signature to the interface.
*
* @param value - The type guard for values accessed by the index signature.
* @param enforce - Whether to enforce that there is at least one property already set. Be careful setting this to
* false, you will get some unexpected outputs, for instance arrays will have a string index signature.
*/
withNumericIndexSignature: <V>(value: TypeGuard<V>, enforce?: boolean) => InterfaceBuilder<T & Record<number, V>>;
/**
* Add many properties to the interface at once.
*
* @param props - A map of properties to guards to apply to the interface.
*/
withProperties: <V extends object>(props: MappedTypeGuard<V>) => InterfaceBuilder<T & V>;
/**
* Add many optional properties to the interface at once.
*
* @param props - A map of properties to guards to apply to the interface.
*/
withOptionalProperties: <V extends object>(props: MappedTypeGuard<V>) => InterfaceBuilder<T & Partial<V>>;
}
/**
* A small class to help with constructing larger intersection checkers.
*
* @public
*/
export declare class IntersectionOf<B, T extends B> {
private readonly ptt;
constructor(ptt: PartialTypeGuard<B, T>);
/**
* Finalise and return the partial type guard for this builder.
*/
get(): PartialTypeGuard<B, T>;
/**
* Add a new option for this intersection.
*/
with<U extends B>(ptu: PartialTypeGuard<B, U>): IntersectionOf<B, T & U>;
}
/**
* Helper for asserting nothing at all.
*
* Note: this is very rarely useful. You probably want isSet. isAny
* allows null and undefined through as well - it matches TypeScripts type
* and simply returns a static true because anything is an any.
*
* You can use isSet to validate that a value is non-null then let TypeScript
* widen it back to any in your interface.
*
* @public
*/
export declare const isAny: TypeGuard<unknown>;
/**
* Validate if a value is an array of a specific type of value.
*
* @public
*/
export declare const isArray: <T>(valueCheck: TypeGuard<T>) => TypeGuard<T[]>;
/**
* Validate if a value is a boolean.
*
* @public
*/
export declare const isBoolean: TypeGuard<boolean>;
/**
* Alias for isFloat.
*
* @see isFloat()
* @public
*/
export declare const isDouble: TypeGuard<number>;
/**
* Validates that a value is one of a set of values.
*
* @public
*/
export declare const isElementOf: {
(): TypeGuard<never>;
<T>(...ss: T[]): TypeGuard<T>;
};
/**
* Validate that an object has exactly the fields provided.
*
* @public
*/
export declare const isExactObject: <V extends object>(props: MappedTypeGuard<V>) => TypeGuard<V>;
/**
* Validate the value is a finite number.
*
* @public
*/
export declare const isFiniteNumber: TypeGuard<number>;
/**
* Validate the value is a number in the rawest sense.
*
* This check is exactly what the type system says on the tin. This value is a floating point value with all
* the edge cases that entails.
*
* @public
*/
export declare const isFloat: TypeGuard<number>;
/**
* Validate the value is infinite.
*
* @public
*/
export declare const isInfinity: TypeGuard<number>;
/**
* Validates that a given object is an instance of a class.
*
* @public
*/
export declare const isInstance: <T extends object>(klass: abstract new (...args: never[]) => T) => TypeGuard<T>;
/**
* A small class to help with constructing interface guards.
*
* @public
*/
export declare class IsInterface implements InterfaceBuilder<object> {
get(): TypeGuard<object>;
with<V extends object>(ptv: PartialTypeGuard<object, V>): InterfaceBuilder<V>;
withProperty<K extends string, V>(key: K, ptv: TypeGuard<V>): InterfaceBuilder<Record<K, V>>;
withOptionalProperty<K extends string, V>(key: K, ptv: TypeGuard<V>): InterfaceBuilder<object & Partial<Record<K, V>>>;
withStringIndexSignature<V>(value: TypeGuard<V>, enforce?: boolean): InterfaceBuilder<Record<string, V>>;
withNumericIndexSignature<V>(value: TypeGuard<V>, enforce?: boolean): InterfaceBuilder<Record<number, V>>;
withProperties<V extends object>(props: MappedTypeGuard<V>): InterfaceBuilder<object & V>;
withOptionalProperties<V extends object>(props: MappedTypeGuard<V>): InterfaceBuilder<object & Partial<V>>;
}
/**
* Check if a value is an intersection of two types.
*
* @public
*/
export declare const isIntersection: <B, T extends B, U extends B>(ptt: PartialTypeGuard<B, T>, ptu: PartialTypeGuard<B, U>) => PartialTypeGuard<B, T & U>;
/**
* Validate that an object has the fields provided.
*
* @public
*/
export declare const isLikeObject: <V extends object>(props: MappedTypeGuard<V>) => TypeGuard<V>;
/**
* Validates if a value is a given type or null or undefined.
*
* @public
*/
export declare const isMissing: <T>(tgt: TypeGuard<T>) => TypeGuard<T | undefined | null>;
/**
* Validates a value is exactly the NaN constant value.
*
* @public
*/
declare const isNaN_2: TypeGuard<number>;
export { isNaN_2 as isNaN }
/**
* Helper for exhaustiveness checking.
*
* @public
*/
export declare const isNever: (n: never) => never;
/**
* Validate if a value is a non-empty array of a specific type of value.
*
* @public
*/
export declare const isNotEmptyList: <T>(valueCheck: TypeGuard<T>) => TypeGuard<[T, ...T[]]>;
/**
* Validate if a value is the constant null.
*
* @public
*/
export declare const isNull: TypeGuard<null>;
/**
* Validate if a value is a given type or null.
*
* @public
*/
export declare const isNullable: <T>(tgt: TypeGuard<T>) => TypeGuard<T | null>;
/**
* Validate if a value is a javascript number.
*
* @public
*/
export declare const isNumber: TypeGuard<number>;
/**
* Validates if a value is a valid part of a numeric enumeration.
*
* @param e - The enumeration to check
* @param flags - Whether this is a flag style enumeration
*
* @public
*/
export declare const isNumericalEnumeration: <T extends Record<string | number, string | number>>(e: T, flags?: boolean) => TypeGuard<T>;
/**
* Validate if a value is an object.
*
* @public
*/
export declare const isObject: TypeGuard<object>;
/**
* Validate if a value is like an object.
*
* Specifically, this only checks typeof === "object" which includes
* things that typescript has other primitives for like arrays.
*
* @public
*/
export declare const isObjectLike: TypeGuard<object>;
/**
* Validate if a value is optionally a given type.
*
* @public
*/
export declare const isOptional: <T>(tgt: TypeGuard<T>) => TypeGuard<T | undefined>;
/**
* Validate that a variable is an object with a single field.
*
* If you need multiple fields then use hasProperties.
*
* @public
*/
export declare const isRecord: <K extends string, V>(property: K, value: TypeGuard<V>) => TypeGuard<Record<K, V>>;
/**
* Validates if a value is not null and not undefined.
*
* @public
*/
export declare const isSet: <T = unknown>(obj: T) => obj is Diff<T, undefined | null>;
/**
* Validate if an object is a Set containing elements of a given type.
*
* @public
*/
export declare const isSetOf: <T>(tg: TypeGuard<T>) => (o: unknown) => o is Set<T>;
/**
* Validate if a value is a specific javascript number.
*
* @public
*/
export declare const isSingletonNumber: <T extends number>(v: T) => TypeGuard<T>;
/**
* Validate if a value is one of a set of specific numbers.
*
* @public
*/
export declare const isSingletonNumberUnion: {
(): TypeGuard<never>;
<T extends number>(...ss: T[]): TypeGuard<T>;
};
/**
* Validate if a value is a specific string.
*
* @public
*/
export declare const isSingletonString: <T extends string>(v: T) => TypeGuard<T>;
/**
* Validate if a value is one of a set of specific strings.
*
* @public
*/
export declare const isSingletonStringUnion: {
(): TypeGuard<never>;
<T extends string>(...ss: T[]): TypeGuard<T>;
};
/**
* Validate if a value is a string.
*
* @public
*/
export declare const isString: TypeGuard<string>;
/**
* Validates if a value is a valid part of a string enumeration.
*
* @param e - The enumeration to check
*
* @public
*/
export declare const isStringEnumeration: <T extends Record<string, string>>(e: T) => TypeGuard<T>;
/**
* Validate if a value is the constant undefined.
*
* @public
*/
export declare const isUndefined: TypeGuard<undefined>;
/**
* Check if a value is a union of two types.
*
* @public
*/
export declare const isUnion: <B, T extends B, U extends B>(ptt: PartialTypeGuard<B, T>, ptu: PartialTypeGuard<B, U>) => PartialTypeGuard<B, T | U>;
/**
* Alias for isAny.
*
* @see isAny
* @public
*/
export declare const isUnknown: TypeGuard<unknown>;
/**
* An object of type guards based on the input type.
*
* @public
*/
export declare type MappedTypeGuard<T> = {
[P in keyof T]: TypeGuard<T[P]>;
};
/**
* Narrow the type of elements inside an array.
*
* @public
*/
export declare const narrowArray: <T, U extends T>(pt: PartialTypeGuard<T, U>) => PartialTypeGuard<T[], U[]>;
/**
* Narrow the type of a value.
*
* @public
* @deprecated Use combine instead, this alias is poorly named.
*/
export declare const narrowValue: <T, U extends T, V extends U>(ptt: PartialTypeGuard<T, U>, ptu: PartialTypeGuard<U, V>) => PartialTypeGuard<T, V>;
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/**
* A partial type guard that can take a value of one type and determine if it is also a valid value of a subtype.
*
* @public
*/
export declare type PartialTypeGuard<T, U extends T> = (value: T) => value is U;
/**
* A full type guard that can guard any value and determine if it is valid.
*
* @public
*/
export declare type TypeGuard<T> = PartialTypeGuard<unknown, T>;
/**
* A small class to help with constructing larger union checkers.
*
* @public
*/
export declare class UnionOf<B, T extends B> {
private readonly ptt;
constructor(ptt: PartialTypeGuard<B, T>);
/**
* Finalise and return the partial type guard for this builder.
*/
get(): PartialTypeGuard<B, T>;
/**
* Add a new option for this union.
*/
with<U extends B>(ptv: PartialTypeGuard<B, U>): UnionOf<B, T | U>;
}
export { }