首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用约束创建映射类型的对象

使用约束创建映射类型的对象
EN

Stack Overflow用户
提问于 2020-01-24 18:58:22
回答 1查看 153关注 0票数 1

this问题类似,我正在尝试创建一个映射类型的对象。但是,我在实现过程中总是遇到类型错误。

下面是一个玩具示例:

代码语言:javascript
运行
复制
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提供以下类型错误

代码语言:javascript
运行
复制
const result: MakeArrayedAll<FS>
Type 'ArrayedReturnFunction<any>' is not assignable to type 'MakeArrayed<FS[keyof FS]>'.(2322)

与上一个问题的不同之处在于,需要通过FS extends SingleArgFunctionObject约束未映射类型FS的属性。除了断言result as any之外,还有其他解决方案吗

Playground

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-24 23:18:06

我倾向于重构您的类型,以避免条件类型(编译器很难理解),而是尽可能使用映射类型和映射类型的推断。在我看来,您的makeArrayed()函数没有问题。

我将把SingleArgFunctionObjectArrayedReturnFunctionObject定义为它所映射的对象类型AS中的泛型...其思想是将AS的每个属性视为SingleArgFunction<A>ArrayedReturnFunction<A>中的A

代码语言:javascript
运行
复制
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()方法更容易做到这一点:

代码语言:javascript
运行
复制
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]

好的,希望这会有帮助;祝你好运!

Playground link

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59895071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档