1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix type errors using raw InputValidator (#5704)

- Introduce LegacyInputValidator type

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-07-05 11:56:41 -07:00 committed by GitHub
parent 6d484a45e5
commit eddefb2074
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 31 deletions

View File

@ -3,6 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { InputValidator } from "../input_validators";
import { isEmail, isUrl, systemName, unionInputValidators, unionInputValidatorsAsync } from "../input_validators"; import { isEmail, isUrl, systemName, unionInputValidators, unionInputValidatorsAsync } from "../input_validators";
type TextValidationCase = [string, boolean]; type TextValidationCase = [string, boolean];
@ -146,4 +147,12 @@ describe("input validation tests", () => {
expect(systemName.validate(input)).toBe(output); expect(systemName.validate(input)).toBe(output);
}); });
}); });
it("should allow InputValidator to be used without any type params", () => {
const v: InputValidator = {
validate: (input: string) => input.length > 10,
};
expect(v.validate("hello")).toBe(false);
});
}); });

View File

@ -178,7 +178,11 @@ export class Input extends React.Component<InputProps, State> {
break; break;
} }
if (isAsyncValidator(validator)) { const result = validator.validate(value, this.props);
if (typeof result === "boolean" && !result) {
errors.push(this.getValidatorError(value, validator));
} else if (result instanceof Promise) {
if (!validationId) { if (!validationId) {
this.validationId = validationId = uniqueId("validation_id_"); this.validationId = validationId = uniqueId("validation_id_");
} }
@ -189,8 +193,6 @@ export class Input extends React.Component<InputProps, State> {
return this.getValidatorError(value, validator) || (error instanceof Error ? error.message : String(error)); return this.getValidatorError(value, validator) || (error instanceof Error ? error.message : String(error));
} }
})()); })());
} else if (!validator.validate(value, this.props)) {
errors.push(this.getValidatorError(value, validator));
} }
} }

View File

@ -18,38 +18,58 @@ export type InputValidation<IsAsync extends boolean> = (value: string, props?: I
export type SyncValidationMessage = React.ReactNode | ((value: string, props?: InputProps) => React.ReactNode); export type SyncValidationMessage = React.ReactNode | ((value: string, props?: InputProps) => React.ReactNode);
export type InputValidator<IsAsync extends boolean = boolean> = { /**
* @deprecated This type is not as type safe as it is possible to specify an async input validator without specifying a `debounce` time.
*
* Use {@link asyncInputValidator} or {@link inputValidator} instead to create validators
*/
export interface LegacyInputValidator {
/** /**
* Filters itself based on the input props * Filters itself based on the input props
*/ */
condition?: (props: InputProps) => any; condition?: (props: InputProps) => any;
} & ( validate: InputValidation<boolean>;
IsAsync extends true message?: SyncValidationMessage;
? { debounce?: number;
/** }
* The validation message maybe either specified from the `message` field (higher priority)
* or if that is not provided then the message will retrived from the rejected with value
*/
validate: InputValidation<true>;
message?: SyncValidationMessage;
debounce: number;
}
: {
validate: InputValidation<false>;
message: SyncValidationMessage;
debounce?: undefined;
}
);
export function isAsyncValidator(validator: InputValidator<boolean>): validator is InputValidator<true> { export interface AsyncInputValidator {
/**
* Filters itself based on the input props
*/
condition?: (props: InputProps) => any;
validate: InputValidation<true>;
message?: SyncValidationMessage;
debounce: number;
}
export interface SyncInputValidator {
/**
* Filters itself based on the input props
*/
condition?: (props: InputProps) => any;
validate: InputValidation<false>;
message: SyncValidationMessage;
debounce?: undefined;
}
export type InputValidator<IsAsync extends boolean = boolean> = SyncInputValidator | AsyncInputValidator | (IsAsync extends boolean ? LegacyInputValidator : never);
export function isAsyncValidator(validator: InputValidator): validator is AsyncInputValidator {
return typeof validator.debounce === "number"; return typeof validator.debounce === "number";
} }
export function asyncInputValidator(validator: InputValidator<true>): InputValidator<true> { /**
* A helper function to create an {@link AsyncInputValidator}
*/
export function asyncInputValidator(validator: AsyncInputValidator): AsyncInputValidator {
return validator; return validator;
} }
export function inputValidator(validator: InputValidator<false>): InputValidator<false> { /**
* A helper function to create an {@link SyncInputValidator}
*/
export function inputValidator(validator: SyncInputValidator): SyncInputValidator {
return validator; return validator;
} }
@ -58,9 +78,9 @@ export function inputValidator(validator: InputValidator<false>): InputValidator
* one of the input validators matches the input * one of the input validators matches the input
*/ */
export function unionInputValidators( export function unionInputValidators(
baseValidator: Pick<InputValidator<false>, "condition" | "message">, baseValidator: Pick<SyncInputValidator, "condition" | "message">,
...validators: InputValidator<false>[] ...validators: SyncInputValidator[]
): InputValidator<false> { ): SyncInputValidator {
return inputValidator({ return inputValidator({
...baseValidator, ...baseValidator,
validate: (value, props) => validators.some(validator => validator.validate(value, props)), validate: (value, props) => validators.some(validator => validator.validate(value, props)),
@ -72,13 +92,13 @@ export function unionInputValidators(
* valid if one of the input validators matches the input * valid if one of the input validators matches the input
*/ */
export function unionInputValidatorsAsync( export function unionInputValidatorsAsync(
baseValidator: SetRequired<Pick<InputValidator<boolean>, "condition" | "message">, "message">, baseValidator: SetRequired<Pick<InputValidator, "condition" | "message">, "message">,
...validators: InputValidator<boolean>[] ...validators: InputValidator[]
): InputValidator<true> { ): AsyncInputValidator {
const longestDebounce = Math.max( const longestDebounce = Math.max(
...validators ...validators
.filter(isAsyncValidator) .filter(isAsyncValidator)
.map(validator => validator.debounce), .map(validator => validator.debounce ?? 0),
0, 0,
); );