简体   繁体   English

如何在 typescript 中同时声明泛型箭头 function 的返回类型为数组和值?

[英]How to declare the return type of a generic arrow function to be an array and value at the same time in typescript?

Consider a function which takes an array, property name and an arrow function as arguments.考虑一个 function,它采用一个数组、属性名称和一个箭头 function 作为 arguments。 What I want to achieve is, filter the array and overwrite the mentioned property's value with an array (output of the arrow function) based on the length check.我想要实现的是,过滤数组并根据长度检查用数组(箭头函数的输出)覆盖提到的属性值。

overwriteFieldWith<T1, T2 extends T1[keyof T1]>(
      input: Array<T1>, property: keyof T1, onOverwrite: (i: T1) => T2
): T[] {
   // filter the input array and replace the property for
   // each item with the output of the supplied arrow function
   return input.filter(i => {
       const value = onOverwrite(i);
       if(value.length) {  // giving me error 'length does not exist on type T2'
          i[property] = value;
          console.log(i);
          return true;
       } else {
          return false;
       }
   });
}

It gives me error when I try to do length check on it.当我尝试对其进行长度检查时,它给了我错误。 The supplied arrow function is always going to return an array but how can I satisfy the compiler on this?提供的箭头 function 总是会返回一个数组,但我怎样才能满足编译器的要求呢?

Edit: Link to the ts playground.编辑:链接到 ts 操场。

Here's one approach:这是一种方法:

overwriteFieldWith<T, K extends keyof T>(
    input: Array<T>,
    property: K,
    onOverwrite: (i: T) => Extract<T[K], readonly any[]>
): T[] {
    return input.filter(i => {
        const value = onOverwrite(i);
        if (value.length) {
            i[property] = value;
            return true;
        } else {
            return false;
        }
    });
}

I made the function generic in the type K of property , so that the type checker keeps track of which property we're talking about.我在property的类型K中创建了 function泛型,以便类型检查器跟踪我们正在谈论属性。 That way we can require that onOverWrite() actually return something assignable to that property value instead of something else... we need to know this or else i[property] = value might be unsafe.这样我们就可以要求onOverWrite()实际上返回可分配给属性值的东西而不是其他东西......我们需要知道这一点,否则i[property] = value可能是不安全的。

I also made the return type of onOverwrite() just Extract<T[K], readonly any[]> using the Extract<T, U> union filtering utility type instead of some generic U extends T[K] .我还使用Extract<T, U>联合过滤实用程序类型而不是一些通用的U extends T[K]onOverwrite()的返回类型设置为Extract<T[K], readonly any[]>

(Note that the readonly any[] type is wider than just any[] ; we don't care about modifying the array so we don't need to require mutable methods to exist). (请注意, readonly any[]类型any[]更宽;我们不关心修改数组,因此我们不需要存在可变方法)。

This serves the purpose of convincing the compiler that value.length will exist (since the compiler accepts that Extract<T, U> is assignable to both T and U , so the compiler knows that value is an readonly any[] ).这有助于使编译器相信value.length将存在(因为编译器接受Extract<T, U>可分配给TU ,因此编译器知道valuereadonly any[] )。 It also serves the purpose of requiring that onOverwrite() return only those union members of the property type T[K] that are arrays.它还用于要求onOverwrite()仅返回属性类型为T[K]且为 arrays 的联合成员。 This works for your example use case at any rate.无论如何,这适用于您的示例用例。


Let's test it:让我们测试一下:

const filtered = a.overwriteFieldWith(elementTypes, 'elements', (i) =>
    i?.elements?.filter(data => !data.hide) ?? []);
/* (method) A.overwriteFieldWith<ElementType, "elements">(input: ElementType[], 
   property: "elements", onOverwrite: (i: ElementType) => TElement[]
): ElementType[] */

Looks good.看起来不错。 Note that the compiler inferred T as ElementType and K as "elements" , and thus that the return type of onOverwrite() is TElment[] as demonstrated here:请注意,编译器将T推断为ElementType并将K推断为"elements" ,因此onOverwrite()的返回类型是TElment[] ,如下所示:

type TK = ElementType['elements'];
//type TK = TElement[] | undefined

type XTK = Extract<ElementType['elements'], readonly any[]>
// type XTK = TElement[]

So an ElementType might have an undefined elements property, but onOverwrite cannot return undefined .所以ElementType可能有一个未定义的elements属性,但onOverwrite不能返回undefined

Playground link to code Playground 代码链接

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

相关问题 在Typescript中,我如何声明一个返回字符串类型数组的函数? - In Typescript how do I declare a function that return string type array? 如何在Typescript中声明一个变量类型的数组? - How to declare an array of type of a variable in Typescript? 如何强制返回类型的数组到打字稿函数 - How to force a return type of Array onto typescript function 预期返回箭头中的值; function 数组回调返回。 为什么? - Expected to return a value in arrow; function array-callback-return. Why? 如何映射到对象数组? (错误“Array.prototype.map() 需要箭头函数的返回值”) - How to map on a array of object ? (error "Array.prototype.map() expects a return value from arrow function") 如何在Typescript中声明自定义类型的N个元素的数组? - How to declare array of N elements of custom type in Typescript? 如何通过箭头分配数组元素的值 function - How to assign value of array element by a arrow function 如何在具有返回类型int []的函数中声明未知长度的整数数组? - How can I declare an integer array of unknown length in a function that has return type int[]? 打字稿换行数组通用类型 - typescript wrap Array Generic type 如何在 Swift 中使函数的返回类型通用 - How to make return type of function generic in Swift
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM