Typescript泛型实例化



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

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);

这是一个可行的方法吗?我需要改变什么才能得到想要的结果?

看起来你混淆了你的类型(即来自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();

最新更新