Home > OS >  TS, implicit inference based on the return type of the first element of a tuplue
TS, implicit inference based on the return type of the first element of a tuplue

Time:10-31

I need to validate a ts inference like this one

interface Animal {
  name: string;

  color: string;

  age: number;
}
type Validator<T> = (data: T) => boolean;

const validateString: Validator<string> = (data) => !!data?.length;
const validateNumber: Validator<number> = (data) => data > 0;

// this type should have ts inference
type ValidatorTuple<T> = [(data: T) => unknown, Validator<unknown>];

const validate = <T>(item: T, validator: ValidatorTuple<T>[]) => {
  for (const [predicate, validation] of validator) {
    const value = predicate(item);

    const result = validation(value);

    if (!result) return false;
  }

  return true;
};

//expected result

const dog: Animal = {
  age: 12,
  color: "white",
  name: "josh",
};

const isValid = validate(dog, [
  [(d) => d.age, validateNumber],
  [(d) => d.color, validateString],
  [(d) => d.name, validateNumber], // this should throw a TS error
]);

I've tried many ts inference but nothing works

CodePudding user response:

Turns out that your unknown's were causing the compiler some trouble (see @geoffrey's comment). Changing them to any allowed me to do this (it's OK since it won't "bleed" into the rest of the code):

const validate = <T, V extends [(data: T) => any, Validator<any>][]>(item: T, validator: [...{
  [K in keyof V]: V[K] extends [(data: T) => infer U, Validator<infer X>]
    ? [U] extends [X]
      ? V[K]
      : [TypeError, "Validator type does not match with value provider."]
    : V[K];
}]) => {

Essentially, we're allowing the compiler to infer the type of V first, then "looping" over V and checking if the validator and "value provider" match. If it doesn't, we "replace" that element with a type error instead.

And as an unintended effect, the body of the function is unaffected. Mainly because the values are now any - but that is OK (and technically correct).

Playground

  • Related