简体   繁体   English

Typescript 联合类型的功能

[英]Typescript union type for functions

I have a problem with understanding of Typescript type describing my validation functions.我对描述我的验证功能的 Typescript 类型的理解有疑问。 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:这些是我与这些 function 类型一起使用的函数:

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:当我使用上述函数创建一个数组并在 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:我收到字段 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; (属性)fieldValue:从不类型“字符串”不可分配给类型“从不”。(2322)input.tsx(9、2):预期类型来自属性“fieldValue”,它在类型“ValidationFunctionType & {字段值:字符串; args: { minLength: number;参数:{ minLength:数字; }; }; } & { fieldValue: number; } & { 字段值:数字; args: { minNumber: number;参数:{ minNumber:数字; }; }; } & { fieldValue: Date; } & { 字段值:日期; args: {...;参数:{...; }; }; }' }'

And for args field:对于 args 字段:

(property) args: { minLength: number; (属性)参数:{ minLength:数字; } & { minNumber: number; } & { minNumber: number; } & { maxYear: Date; } & { maxYear: 日期; } Type '{ minLength: number; } 类型 '{ minLength: number; }' is not assignable to type '{ minLength: number; }' 不可分配给类型 '{ minLength: number; } & { minNumber: number; } & { minNumber: number; } & { maxYear: Date; } & { maxYear: 日期; }'. }'。 Property 'minNumber' is missing in type '{ minLength: number; '{ minLength: number; 类型中缺少属性 'minNumber' }' but required in type '{ minNumber: number; }' 但在 '{ minNumber: number; 类型中是必需的}'.(2322) }'.(2322)

Why these types for field args and fieldName are connected with & operator instead of |为什么字段 args 和 fieldName 的这些类型使用 & 运算符而不是 | operator?操作员? How to create a type for these functions which will be correct and more generic?如何为这些函数创建一个正确且更通用的类型?

The whole code example in TS playground: Code TS 操场中的整个代码示例: 代码

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:这种类型似乎适用于 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.每个 function 都需要在开始时验证 fieldName 和 args 类型。

This seems to be a classic case of function overloading .这似乎是function 重载的经典案例。

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最后,您的validate实现应该支持每种情况 - 您可以使用 类型保护进行类型检查

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

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 .如果 function 期待MinLengthType ,那么您在这里传递的值是有意义的。 But since data.func is a ValidationFunctionsType , the type doesn't actually show that that's the expected data.但由于data.funcValidationFunctionsType ,该类型实际上并没有表明这是预期的数据。 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. function 可能会期望MinNumberTypeMaxYearType ,而您通过的 object 将是错误的,因此 typescript 显示错误。

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.由于您可能要处理 3 个可能的函数,因此 typescript 将只允许您传入与所有 3 个函数匹配的值。 Ie, you can pass in the intersection of all 3 types: MinLengthType & MinNumberType & MaxYearType .即,您可以传入所有 3 种类型的交集: 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.不幸的是,这个交集是不可能遵守的,因为它需要相互排斥的东西,比如fieldValue同时是一个string 、一个number和一个Date So there is no way to legally call data.func .所以没有办法合法地调用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?如果你收到一个 function ,比如MaxYearType ,你想做什么? Call the function with some alternate data;使用一些备用数据调用 function; not call it at all;根本不叫它; something else?别的东西? Also, how do you intend to identify which function variant you have?另外,您打算如何识别您拥有的 function 变体?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM