[英]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 总是会返回一个数组,但我怎样才能满足编译器的要求呢?
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>
可分配给T
和U
,因此编译器知道value
是readonly 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
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.