与this问题类似,我正在尝试创建一个映射类型的对象。但是,我在实现过程中总是遇到类型错误。
下面是一个玩具示例:
type SingleArgFunction<A> = (x: A) => A;
type ArrayedReturnFunction<A> = (x: A) => A[];
// create an arrayed function from a single arg function
type MakeArrayed<F> = F extends SingleArgFunction<infer A> ? ArrayedReturnFunction<A> : never;
// mapped type
type MakeArrayedAll<FS> = {
[K in keyof FS]: MakeArrayed<FS[K]>
}
// example usage
type MyFunctions = {
foo: SingleArgFunction<number>,
bar: SingleArgFunction<string>
}
type MyArrayedFunctions = MakeArrayedAll<MyFunctions> // ok
// functions to convert an object of single arg functions to object of arrayed functions
interface SingleArgFunctionObject {
[key: string]: SingleArgFunction<any>
}
function makeArrayed<A>(f: SingleArgFunction<A>): ArrayedReturnFunction<A> {
return function (x) {
return [f(x)];
}
}
function makeArrayedAll<FS extends SingleArgFunctionObject>(fs: FS): MakeArrayedAll<FS> {
const keys = Object.keys(fs) as (keyof FS)[];
const result = {} as MakeArrayedAll<FS>;
for (let key of keys) {
result[key] = makeArrayed(fs[key]);
}
return result;
}这将为result提供以下类型错误
const result: MakeArrayedAll<FS>
Type 'ArrayedReturnFunction<any>' is not assignable to type 'MakeArrayed<FS[keyof FS]>'.(2322)与上一个问题的不同之处在于,需要通过FS extends SingleArgFunctionObject约束未映射类型FS的属性。除了断言result as any之外,还有其他解决方案吗
发布于 2020-01-24 23:18:06
我倾向于重构您的类型,以避免条件类型(编译器很难理解),而是尽可能使用映射类型和映射类型的推断。在我看来,您的makeArrayed()函数没有问题。
我将把SingleArgFunctionObject和ArrayedReturnFunctionObject定义为它所映射的对象类型AS中的泛型...其思想是将AS的每个属性视为SingleArgFunction<A>和ArrayedReturnFunction<A>中的A
type SingleArgFunctionObject<AS extends object> = {
[K in keyof AS]: SingleArgFunction<AS[K]>
}
type ArrayedReturnFunctionObject<AS extends object> = {
[K in keyof AS]: ArrayedReturnFunction<AS[K]>
}有了这一点,makeArrayedAll()将成为AS中的泛型。让编译器不抱怨的棘手之处在于让for循环将每个key视为一个通用K extends keyof AS。使用数组的forEach()方法更容易做到这一点:
function makeArrayedAll<AS extends object>(
fs: SingleArgFunctionObject<AS>
): ArrayedReturnFunctionObject<AS> {
const result = {} as ArrayedReturnFunctionObject<AS>;
(Object.keys(fs) as (keyof AS)[]).forEach(<K extends keyof AS>(key: K) => {
result[key] = makeArrayed(fs[key]);
})
return result;
}这应该会产生与您的代码相同的结果,但是现在编译器更加确信类型为ArrayedReturnFunction<AS[K]>的makeArrayed(fs[key])可以赋值给类型为ArrayedReturnFunctionObject<AS>[K]的result[key]。
好的,希望这会有帮助;祝你好运!
https://stackoverflow.com/questions/59895071
复制相似问题