Typescript:如何将对象映射到类型?

7
假设我有一个包含一些数据的对象。我想要构建一个通用映射器(只是一个函数,我不想一直实例化新类),以便所有类型都可以像这样使用:this.responseMapper.map<CommentDTO>(data); 它应该简单地获取给定类型的所有属性并将数据映射到其中。 我迄今为止尝试过的方法:
public map<T>(values: any): T {
    const instance = new T();

    return Object.keys(instance).reduce((acc, key) => {
        acc[key] = values[key];
        return acc;
    }, {}) as T;
}

new T(); 会抛出一个错误:'T' 仅表示类型,但在此处被用作值。

应该如何正确处理?


如果你添加一个参数 type: typeof T 并调用 new type(),它会编译吗? - cbr
不,它并不是重复的,因为我不想一直实例化新的映射器类。 - sandrooco
我明白了,感谢您的澄清。措辞让人觉得这正是您想要做的事情。如果您只是想过滤掉不属于该类型键的键,则一些函数库将此操作称为pick - cbr
那你介意去掉这个标志吗? - sandrooco
我可以投票以重新开放,就像我可以投票关闭一样。我会这样做的。您可以通过编辑来澄清您的问题,这将使问题进入重新开放队列。 - cbr
1个回答

6

您需要将类型构造函数传递给该方法。Typescript在运行时擦除泛型,因此无法在运行时了解T。此外,我会将values进行一些调整,以仅允许传递T的成员。这可以使用Partial<T>来完成。

public map<T>(values: Partial<T>, ctor: new () => T): T {
    const instance = new ctor();

    return Object.keys(instance).reduce((acc, key) => {
        acc[key] = values[key];
        return acc;
    }, {}) as T;
 }

使用方法:

class Data {
    x: number = 0; // If we don't initialize the function will not work as keys will not return x
}

mapper.map({ x: 0 }, Data)

这很有道理 - 如果我记录instance,我看不到它的任何属性? new () => T语法如何工作?有关此主题的文档吗? - sandrooco
1
这完全取决于类的定义方式。如果你只是声明属性,直到它们被赋值为止,在运行时你将看不到任何值。new ()=> T 是一个构造函数签名,将执行类的构造函数。在上面的例子中,这相当于说 new Data() - Titian Cernicova-Dragomir
修改了代码以初始化 x,以突出需要初始化而不仅仅是声明字段的观点。 - Titian Cernicova-Dragomir
感谢您提供的出色解释! - sandrooco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接