"TypeScript和字段初始化器"

13 浏览
0 Comments

"TypeScript和字段初始化器"

如何在TS中这样初始化一个新类(以C#示例为例来说明我想要的):

// ... some code before
return new MyClass { Field1 = "ASD", Field2 = "QWE" };
// ...  some code after

admin 更改状态以发布 2023年5月22日
0
0 Comments

更新

自从撰写这个答案以来,有更好的方法出现了。请参阅下面有更多投票和更好答案的其他答案。由于被标记为已接受,我不能删除此答案。


旧答案

在 TypeScript 的 CodePlex 上有一个描述这个问题的问题: 支持对象初始化器

如所述,您可以通过在 TypeScript 中使用接口而不是类来实现此目的:

interface Name {
    givenName: string;
    surname: string;
}
class Person {
    name: Name;
    age: number;
}
var bob: Person = {
    name: {
        givenName: "Bob",
        surname: "Smith",
    },
    age: 35,
};

0
0 Comments

更新于07/12/2016:Typescript 2.1推出了映射类型并提供了 Partial,使您可以实现这个操作...

class Person {
    public name: string = "default"
    public address: string = "default"
    public age: number = 0;
    public constructor(init?:Partial) {
        Object.assign(this, init);
    }
}
let persons = [
    new Person(),
    new Person({}),
    new Person({name:"John"}),
    new Person({address:"Earth"}),    
    new Person({age:20, address:"Earth", name:"John"}),
];

原始回答:

我的方法是为构造函数定义一个单独的fields变量。诀窍是将此初始化器的所有类字段重定义为可选项。当对象被创建(带有其默认值)时,您只需将初始化器对象分配到this中;

export class Person {
    public name: string = "default"
    public address: string = "default"
    public age: number = 0;
    public constructor(
        fields?: {
            name?: string,
            address?: string,
            age?: number
        }) {
        if (fields) Object.assign(this, fields);
    }
}

或者手动进行操作(有点更安全):

if (fields) {
    this.name = fields.name || this.name;       
    this.address = fields.address || this.address;        
    this.age = fields.age || this.age;        
}

用法:

let persons = [
    new Person(),
    new Person({name:"Joe"}),
    new Person({
        name:"Joe",
        address:"planet Earth"
    }),
    new Person({
        age:5,               
        address:"planet Earth",
        name:"Joe"
    }),
    new Person(new Person({name:"Joe"})) //shallow clone
]; 

控制台输出:

Person { name: 'default', address: 'default', age: 0 }
Person { name: 'Joe', address: 'default', age: 0 }
Person { name: 'Joe', address: 'planet Earth', age: 0 }
Person { name: 'Joe', address: 'planet Earth', age: 5 }
Person { name: 'Joe', address: 'default', age: 0 }   

这为您提供了基本的安全性和属性初始化,但这都是可选的,可以无序进行。如果您不传递字段,则保留类的默认值。

您还可以将其与必填的构造函数参数混合使用-将fields放在最后。

我认为这已经很接近C #样式了,(实际的字段初始化语法已被拒绝)。我更喜欢适当的字段初始化器,但似乎不会立即实现。

相比之下,如果您使用转换方法,则您的初始化器对象必须包含您要转换的类型的所有字段,而且不能获得类本身创建的任何类特定函数(或派生)。

0