1

I have a problem with understanding of Typescript type describing my validation functions. These are the types of functions that I use with my code:

type ValidationFunctionType = {
    fieldName: string;
    fields: string;
};

type MaxYearType = ValidationFunctionType & { fieldValue: Date; args: { maxYear: Date } };

type MinLengthType = ValidationFunctionType & {
    fieldValue: string;
    args: { minLength: number };
};

type MinNumberType = ValidationFunctionType & {
    fieldValue: number;
    args: { minNumber: number };
};

Then I create a union type for all the functions:

export type ValidationFunctionsType =
    | (({}: MinLengthType) => string)
    | (({}: MinNumberType) => string)
    | (({}: MaxYearType) => string);

These are the functions that I use with these function types:

const minLength = ({ fieldName, fieldValue, fields, args }: MinLengthType) => {
    return '';
};

const maxYear = ({ fieldName, fieldValue, fields, args }: MaxYearType) => {
    return '';
};

const minNumber = ({ fieldName, fieldValue, fields, args }: MinNumberType) => {
    return '';
};

And when I create an array with the above functions and use them in map:

const validationFunction: { func: ValidationFunctionsType}[] = [{
    func: minLength
  }, { func: maxYear}];

validationFunction.map(data => data.func({ fieldName: 'adfa', fieldValue: 'asdda', fields: 'sd', args: {
    minLength: 5
  } }));

I get the error message for field fieldName:

(property) fieldValue: never Type 'string' is not assignable to type 'never'.(2322) input.tsx(9, 2): The expected type comes from property 'fieldValue' which is declared here on type 'ValidationFunctionType & { fieldValue: string; args: { minLength: number; }; } & { fieldValue: number; args: { minNumber: number; }; } & { fieldValue: Date; args: { ...; }; }'

And for args field:

(property) args: { minLength: number; } & { minNumber: number; } & { maxYear: Date; } Type '{ minLength: number; }' is not assignable to type '{ minLength: number; } & { minNumber: number; } & { maxYear: Date; }'. Property 'minNumber' is missing in type '{ minLength: number; }' but required in type '{ minNumber: number; }'.(2322)

Why these types for field args and fieldName are connected with & operator instead of | operator? How to create a type for these functions which will be correct and more generic?

The whole code example in TS playground: Code

UPDATE

What I want to achieve in this example is to have a correctly designed type for all functions used for validation.

This type seems to work for Typescript:

type ValidationFunctionType = ({fieldName, fields, fieldValue, args}: MinLengthType | MinNumberType | MaxYearType) => string;

Working example But I'm not sure if it is the correct solution. Every function needs validation of fieldName and args type at the beginning.

0

2 Answers 2

1
data.func({ fieldName: 'adfa', fieldValue: 'asdda', fields: 'sd', args: {
  minLength: 5
}}

You're passing in values here that make sense if the function is expecting a MinLengthType. But since data.func is a ValidationFunctionsType, the type doesn't actually show that that's the expected data. The function might instead be expecting a MinNumberType or a MaxYearType, and the object you've passed would be an error for those, hence typescript shows an error.

Since there's 3 possible functions you might be dealing with, typescript will only allow you to pass in values that match all 3 functions. Ie, you can pass in the intersection of all 3 types: MinLengthType & MinNumberType & MaxYearType. Unfortunately, that intersection is impossible to obey because it requires mutually exclusive things like fieldValue being a string, a number, and a Date simultaneously. So there is no way to legally call data.func.

As for how to fix this... I'm not really sure what you're hoping to achieve from this code, so i may need more details. If you receive a function that expects, say, a MaxYearType, what do you want to do? Call the function with some alternate data; not call it at all; something else? Also, how do you intend to identify which function variant you have?

Sign up to request clarification or add additional context in comments.

1 Comment

Basically I want to have an object fo every field in form which looks like: year: { label: 'Year', validationData: [{ validationFunction: maxYear, args: { maxYear: new Date() } }], fieldType: 'date', transformData: value => new Date(value) }, And validate it with functions inserted in validation data array.
0

This seems to be a classic case of function overloading.

In your case, you should implement the signatures:

function validate(fieldName: string, fields: string, fieldValue: Date; args: { maxYear: Date }):string;

function validate(fieldName: string, fields: string, fieldValue: string; args: { maxYear: number }):string;

Finally, your implementation of validate should support every case - you can use type guard for type checking

Reference for function overloading: https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads

1 Comment

I don't think these would be the desired solution for me. I still want to use distinct function names like minLength etc..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.