如何定义一个函数类型transform<I, O>
,它接受类型I的输入并返回类型为O的输出,然后将identity
函数定义为transform
的特定实现?
例如
type transform<I, O> = (input: I) => O;
const identity = // ...
这样我就可以定义一个函数
const mapToObject = <K, V, O>(
map: Map<K, V>,
transformValue: transform<V, O> = identity
) => Array.from(map.entries()).reduce((obj, [key, val]) => {
obj[key] = transformValue(value);
return obj;
}, {});
mapToObject
函数应该使用Map
和transformValue
函数,并将地图转换为简单的JS对象,将transformValue
应用于地图中的每个值。 transformValue
应默认使用identity
函数v => v
。
身份函数映射any
到any
有效,但我对严格类型的解决方案感兴趣。
答案 0 :(得分:1)
只有一种明智的方式来输入身份功能,这里没什么惊喜
const identity = <T>(t: T) => t;
但严格类型的标识函数不能赋予任意变换 - 编译器知道它返回的类型与收到的相同,因此mapToObject
的输入不一致 - 当你将其称为<时,结果类型是什么? / p>
mapToObject<string, number, Date>(new Map<string, number>())
Dates
这需要表示为依赖类型 - 结果对象的类型取决于是给定transform参数还是使用default。在TypeScript中,您可以使用overloading function declarations执行此操作:
function mapToObject<K, V>(map: Map<K, V>)
: { [n: string]: V };
function mapToObject<K, V, O>(map: Map<K, V>, transformValue: transform<V, O>)
: { [n: string]: O };
function mapToObject<K, V, O>(map: Map<K, V>, transformValue?: transform<V, O>)
: { [n: string]: {} }
{
const transform: (v: V) => {} = transformValue || identity;
return Array.from(map.entries()).reduce((obj, [key, val]) => {
obj[key.toString()] = transform(val) ;
return obj;
}, {});
}
由于实际上没有在实现中使用实际值类型,因此它可以作为空对象类型{}
给出,它与V和O类型兼容(您可以使用联合类型V | O
相反,因为它也兼容,但它更冗长,并且在这里没有购买任何东西)
使用这些声明,编译器会检测到不一致的用法:
// error: Expected 1-2 arguments, but got 1
mapToObject<string, number, Date>(new Map<string, number>())
mapToObject<string, number>(new Map<string, number>()) // ok
mapToObject<string, number, Date>(new Map<string, number>(), n => new Date(n)) //ok
并按预期推断结果类型:
const o1 = mapToObject(new Map<string, number>())
// {[n: string]: number}
const o2 = mapToObject(new Map<string, number>(), n => new Date(n))
// {[n: string]: Date}
答案 1 :(得分:0)
您可以将通用参数放入箭头函数或常规函数
type transform<I, O> = (input: I) => O;
const identity = <I, O> (input: I) => {
return null;
}
//Or
const identity2 = function <I, O> (input: I) {
return null;
}
const mapToObject = <K extends string, V, O>(
map: Map<K, V>,
transformValue: transform<V, O> = identity
) => Array.from(map.entries()).reduce((obj, [key, val]) => {
obj[key] = transformValue(val);
return obj;
}, <{ [index: string]: O }>{});