打字稿泛型类型实例化

胜利者

我正在尝试创建一个函数,该函数将实例化给定类型的对象以及嵌套属性(如果有)。于是想出了这个方法。

export function InitializeDefaultModelObject<T extends object> (): T  
{
    const root: T = {} as T;
    Object.keys(root).forEach(key =>
    { 
        if (typeof root[key] === 'object') root[key] =  {};
    });
    return root;
}

问题是当我调用它时,它返回空对象{},而不是我希望创建的类型的对象。

    this.ProjectModel = InitializeDefaultModelObject<ProjectModel>();
    console.table(this.ProjectModel);

这是一种可行的方法吗,我需要改变什么才能获得理想的结果?

用户3781737

看起来您将您的类型(即来自 TypeScript)与您的运行时代码(即 JavaScript)混淆了,我认为对于此类问题的一个很大帮助是了解一个开始和另一个结束的时间。请记住,TS 实际上只是为了在开发过程中为您提供帮助。它的所有类型和其他特殊语法也可能只是注释,因为您的机器永远不会看到它们。事实上,在它编译成 JS(实际上最终在你的机器上运行的代码)之后,它通常看起来与你编写它的方式几乎相同,只是包含所有类型、泛型和其他特定于 TS 的代码令牌已移除。

说到这里,编译后的代码如下所示:

// my-file.js
export function InitializeDefaultModelObject() {
    const root = {};
    Object.keys(root).forEach(key => {
        if (typeof root[key] === 'object')
            root[key] = {};
    });
    return root;
}


// file-that-imported-my-file.js
this.ProjectModel = InitializeDefaultModelObject();
console.table(this.ProjectModel);

特别是如果您已经有使用常规 JS 的经验,这里缺少泛型或类型可能会帮助您更好地理解为什么事情不起作用。照原样,这个函数既不期望也不被赋予任何参数,因此,它总是会有相同的输出(即一个空对象)。

但是,除非您的用例极其有限,否则编写适用于所有场景任何类型对象的高度可扩展的解决方案并不简单。例如,这是一种基于您的原始代码(在 JS 中,这意味着它也可以在 TS 中工作,即使编译器抱怨)的尝试:

export function InitializeDefaultModelObject(originalObj) {
    var sortaCopiedObj = {};
    Object.keys(originalObj).forEach(key => {
        var typeOfField = typeof originalObj[key];
        if (typeOfField === 'object') sortaCopiedObj[key] = {};
    });
    return sortaCopiedObj;
}

当且仅当您传入的对象是文字(即,它们没有原型可以担心继承)时,这才会起作用,您不关心非对象字段的值,并且您不关心'不要关心你复制的对象属性的嵌套字段例如:

var obj1 = { a: {} };
var copy1 = InitializeDefaultModelObject(obj1); // { a: {} } You probably expect this

var obj2 = { a: { innerProperty: {} }, b: "hey!" };
var copy2 = InitializeDefaultModelObject(obj2); // { a: {} } But did you expect this?

为了解决这个问题,您可以在函数中添加一个 else 语句来说明对象以外的值,您还可以递归调用它以继续构建嵌套对象属性。但是,如果涉及原型,那并不能解决问题,而且我担心您可能没有完全意识到这一点。如果你真的只想使用这个函数来复制任意深度的对象文字,很酷,然后继续添加我刚刚提到的那些修复,但可能有更简单的方法。如果你要多次实例化一个已知结构的对象......为什么不把那个对象变成一个类呢?

class MyClass {
    a = { innerProperty: {} };
    b = "hey!";
}

// All of these have the same properties, but they're all unique instances
var x = new MyClass();
var y = new MyClass();
var z = new MyClass();

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章