是否有声明性方法可以将 TypeScipt 数组的每个成员转换为 Object 的完整实例?

Is there a Declarative approach to converting each member of a TypeScipt array to a full instance of an Object?

提问人:Scala Enthusiast 提问时间:3/11/2023 更新时间:3/11/2023 访问量:55

问:

我有一个无法更改的类,显示简化版本。我在课堂上得到了一系列变化。我需要先将类的其余部分添加到数组的每个成员中,然后才能使用它们。

class ValueType {
    name: string;
    size: number = 5;

    constructor(source?: {
        name?: string;
        size?: number;
    }) {
        if (source) {
           Object.assign(this, source);
        }
    }
};

因此,这可以通过将类单独添加到数组的每个成员来完成,这两种方式中的任何一种,但是对于大数组,恕我直言,这是“混乱的代码”。

let test1 = [new ValueType({
    name: 'john',
})];

console.log('tv1 is:', test1[0].size);  // 5

// OR

let test2 = [{
    name: 'paul',
    ...new ValueType()
}];

console.log('tv2 is:', test2[0].size);  // 5

这是我尝试的声明方式,但它不起作用。它不允许您获取未更新项的默认值。

let test3: Partial<ValueType>[] = [{
    name: 'tom',
}];

console.log('tv3 is:', test3[0].size); // undefined

最后,这里有一个命令式的方法,可以实现我想要的,但我不禁认为 TypeScript 有更好的方法来处理类型、实用程序类型、AND、OR 等!

let test4: ValueType[] = [{
    name: 'tom',
}].map(value => Object.assign(value, new ValueType()));

console.log('tv4 is:', test4[0].size);
TypeScript 声明性 复制分配 命令

评论

0赞 cefn 3/11/2023
这是什么意思?是什么意思,为什么需要添加它?an array of variations on the classadd the rest of the class
1赞 apokryfos 3/11/2023
Typescript 提供静态类型分析,但在实际的运行时实用程序中并不多。您共享的代码需要特定的运行时行为,因此您需要查找 Javascript 在实用性方面必须提供的内容。特别是问题在于,您创建了一个与 type 兼容的对象,但不是 类 的实例。在 Typescript 中,类既定义类本身,也定义与类匹配的类型。我认为你的第 4 种方法可能和你能做的一样好,尽管我只会跑一次test3ValueTypeValueTypenew ValueType()
1赞 Scala Enthusiast 3/11/2023
@cefn,我试图举很多例子来说明我的意思。基本上我的对象有 30+ 个属性,每个属性都有一个默认值,我从服务器返回一个由 1000 个项目组成的数组,每个项目都有 3 或 4 个属性。这些项将转换为对象的 和 数组,只是 3 或 4 个属性覆盖了对象中的默认值。希望对您有所帮助?

答:

1赞 Riheldo Melo 3/11/2023 #1

Typescript 不会在运行时向 JS 对象添加代码。 因此,为了实现你想要的东西,你需要声明一个工厂方法(检查工厂模式)。

因此,在您的示例中,工厂将接收参数形式的数据,并返回所需的实例。可以在类中声明工厂函数或静态工厂方法。

工厂即功能

function factoryValueType(data: Partial<ValueType>): ValueType {
    return new ValueType(data);
}

工厂作为静态方法

class ValueType {
    name: string;
    size: number = 5;

    constructor(source?: {
        name?: string;
        size?: number;
    }) {
        if (source) {
            Object.assign(this, source);
        }
    }

    static fabricate(data): ValueType {
        return new ValueType(data);
    }
}

用于初始化 Array 的声明性使用

valueTypeList: ValueType[] = [
    ValueType.fabricate({name: 'John'}), // use factory as static method
    factoryValueType({name: 'Doe'}), // use factory as function
]

您可以利用它来转换 json 对象

valueTypeList: ValueType[] = jsonList.map(obj => factoryValueType(obj));

使用工厂模式更干净、更安全,您可以为您的工厂调试和创建测试。 请记住,没有唯一的解决方案,这个例子只是其中之一。