`_addIssue` blocks `every`, `some` & `check` actions rewrite due to a possible type issue
EltonLobo07 opened this issue · comments
I was trying to rewrite the every
action and I ran into this issue.
Issue
FunctionReference<unknown[], TContext>
reduces to (...args: unknown[]) => TContext
. This creates a problem. Since function parameter types are contravariant (reference: microsoft/TypeScript#18654), the only valid function types that can be assigned are the functions that have unknown
or any
parameter types (reference: microsoft/TypeScript#24439). This is the type error I get while rewriting the action:
Why did I or any other contributor did not run into this issue earlier while writing actions that were merged to rewrite-with-pipe
?
This is because any action's reference passed to _addIssue
is reduced to (requirement: unknown, message?: unknown) => <ReturnTypeOfTheActionHere>
if the action has two or more overloads with generic parameters. Try commenting the first overload of any action maybe bytes
and notice _addIssue
creates a type error.
The requirements of every
, some
and check
are functions so they can't be reduced to unknown
.
My suggestion
Change FunctionReference<unknown[], TContext>
to FunctionReference<any[], TContext>
and update all of the relevant affected places. Reading the implementation, I noticed it doesn't really care about the types of the parameters of the function reference passed to _addIssue
, so it is safe to use any
?
Your suggestion/guidance?
Do you have a better suggestion? Also, I apologize if this was a false alarm. I am trying to limit the help needed so that the rewrite is as smooth as possible but I will need some guidance for this issue.
Incomplete every
implementation so that you can reproduce the issue:
import type { BaseIssue, BaseValidation, ErrorMessage } from '../../types';
import { _addIssue } from '../../utils/index.ts';
/**
* Every issue type.
*/
export interface EveryIssue<TInput extends unknown[]>
extends BaseIssue<TInput> {
/**
* The issue kind.
*/
readonly kind: 'validation';
/**
* The issue type.
*/
readonly type: 'every';
/**
* The expected input.
*/
readonly expected: null;
/**
* The validation function.
*/
readonly requirement: (
element: TInput[number],
index: number,
array: TInput[number][]
) => boolean;
}
/**
* Every action type.
*/
export interface EveryAction<
TInput extends unknown[],
TMessage extends ErrorMessage<EveryIssue<TInput>> | undefined,
> extends BaseValidation<TInput, TInput, EveryIssue<TInput>> {
/**
* The action type.
*/
readonly type: 'every';
/**
* The expected property.
*/
readonly expects: null;
/**
* The validation function.
*/
readonly requirement: (
element: TInput[number],
index: number,
array: TInput[number][]
) => boolean;
/**
* The error message.
*/
readonly message: TMessage;
}
/**
* Creates an every validation action.
*
* @param requirement The validation function.
*
* @returns An every action.
*/
export function every<TInput extends unknown[]>(
requirement: (
element: TInput[number],
index: number,
array: TInput[number][]
) => boolean
): EveryAction<TInput, undefined>;
/**
* Creates an every validation action.
*
* @param requirement The validation function.
* @param message The error message.
*
* @returns An every action.
*/
export function every<
TInput extends unknown[],
const TMessage extends ErrorMessage<EveryIssue<TInput>> | undefined,
>(
requirement: (
element: TInput[number],
index: number,
array: TInput[number][]
) => boolean,
message: TMessage
): EveryAction<TInput, TMessage>;
export function every(
requirement: (element: unknown, index: number, array: unknown[]) => boolean,
message?: ErrorMessage<EveryIssue<unknown[]>>
): EveryAction<unknown[], ErrorMessage<EveryIssue<unknown[]>> | undefined> {
return {
kind: 'validation',
type: 'every',
async: false,
expects: null,
message,
requirement,
_run(dataset, config) {
if (dataset.typed && !dataset.value.every(this.requirement)) {
_addIssue(this, every, 'input', dataset, config);
}
return dataset;
},
};
}
Thank you for creating this issue and the detailed context. I am currently refactoring part of the rewrite. This will include a fix for this problem. I plan to add this change to the rewrite-with-pipe
branch in the next few hours.
Done. Reach out if you have any questions about my changes.