Untitled
unknown
typescript
a year ago
3.9 kB
2
Indexable
Never
import type { HasUndefined, If } from '@twa.js/util-types'; import type { Parser } from './shared.js'; /** * Describes function which returns true in case value should be recognized as empty. */ export type IsEmptyFunc = (value: unknown) => boolean; /** * Describes function which returns default value. */ export type GetDefaultFunc<T> = () => T; /** * Allowed types for "getDefault" method. */ export type AllowedGetDefault = GetDefaultFunc<any> | undefined; /** * Result of "parse" function in ValueParser. */ export type ParseResult< ResultType, IsOptional extends boolean, GetDefault extends AllowedGetDefault, > = | ResultType | If< HasUndefined<GetDefault>, If< IsOptional, undefined, never >, GetDefault extends GetDefaultFunc<infer Default> ? Default : never >; /** * Result of "optional" function in ValueParser. */ export type OptionalResult<BaseClass, ResultType, GetDefault extends AllowedGetDefault> = ValueParserType<BaseClass, ResultType, true, GetDefault>; /** * Result of "default" function in ValueParser. */ export type DefaultResult< BaseClass, ResultType, IsOptional extends boolean, Default, > = ValueParserType<BaseClass, ResultType, IsOptional, GetDefaultFunc<Default>>; export interface ValueParserOverrides< BaseClass, ResultType, IsOptional extends boolean, GetDefault extends AllowedGetDefault, > { /** * Parses incoming value. * @param value - value to parse. */ parse(value: unknown): ParseResult<ResultType, IsOptional, GetDefault>; /** * Marks the value as optional allowing parsing to return undefined value in * case value appeared to be empty. * @param isEmpty - function which returns true in case, value should be recognized as empty. */ optional(isEmpty?: IsEmptyFunc): OptionalResult<BaseClass, ResultType, GetDefault>; /** * Sets function which returns value in case, it appeared to be empty. * @param getDefault - function which returns default value. */ default<Default>( getDefault: GetDefaultFunc<Default>, ): DefaultResult<BaseClass, ResultType, IsOptional, Default>; } /** * Describes generated ValueParser interface. */ export type ValueParserType< BaseClass, ResultType, IsOptional extends boolean, GetDefault extends AllowedGetDefault, > = Omit<BaseClass, keyof ValueParserOverrides<any, any, any, any>> & ValueParserOverrides<BaseClass, ResultType, IsOptional, GetDefault>; export class ValueParser< ResultType, IsOptional extends boolean, GetDefault extends AllowedGetDefault, > { /** * Creates ValueParser only with parser. * @param parser - data parser. */ static create<ResultType>(parser: Parser<ResultType>): ValueParser<ResultType, false, undefined> { return new ValueParser(parser, false, undefined); } constructor( protected parser: Parser<ResultType>, private isOptional: IsOptional, private getDefault: GetDefault, private isEmpty: IsEmptyFunc = (value: unknown) => value === undefined, ) { } parse(value: unknown): ParseResult<ResultType, IsOptional, GetDefault> { if (this.isOptional && this.isEmpty(value)) { return this.getDefault ? this.getDefault() : undefined; } return this.parser(value); } optional(nextIsEmpty?: IsEmptyFunc): OptionalResult<this, ResultType, GetDefault> { this.isOptional = true as IsOptional; if (nextIsEmpty) { this.isEmpty = nextIsEmpty; } return this; } default<Default>( getDefault: GetDefaultFunc<Default>, ): DefaultResult<this, ResultType, IsOptional, Default> { this.getDefault = getDefault as any; return this as DefaultResult<this, ResultType, IsOptional, Default>; } }