如何init一个新的类在TS以这样的方式(在c#的例子,以显示我想要的):
// ... some code before
return new MyClass { Field1 = "ASD", Field2 = "QWE" };
// ... some code after
如何init一个新的类在TS以这样的方式(在c#的例子,以显示我想要的):
// ... some code before
return new MyClass { Field1 = "ASD", Field2 = "QWE" };
// ... some code after
当前回答
type ExcludeMethods<T> = Pick<T, { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]>;
class MyClass {
public name!: string;
public age!: number;
public optional?: boolean;
private yep: string = "";
constructor(props: ExcludeMethods<typeof MyClass.prototype>) {
Object.assign(this, props);
}
public method() {
}
}
const thing = new MyClass({
name: "bob",
age: 15
});
TS操场
其他回答
可以影响类类型中强制转换的匿名对象。 奖励:在visual studio中,你可以这样受益于智能感知:)
var anInstance: AClass = <AClass> {
Property1: "Value",
Property2: "Value",
PropertyBoolean: true,
PropertyNumber: 1
};
编辑:
警告:如果类有方法,类的实例将得不到它们。如果AClass有构造函数,它将不会被执行。如果使用instanceof AClass,则会得到false。
总之,应该使用接口而不是类。 最常见的用途是声明为普通旧对象的域模型。 实际上,对于域模型,您应该更好地使用接口而不是类。接口在编译时用于类型检查,与类不同,接口在编译期间被完全删除。
interface IModel {
Property1: string;
Property2: string;
PropertyBoolean: boolean;
PropertyNumber: number;
}
var anObject: IModel = {
Property1: "Value",
Property2: "Value",
PropertyBoolean: true,
PropertyNumber: 1
};
更新07/12/2016: Typescript 2.1引入了映射类型,并提供了Partial<T>,这允许您这样做....
class Person {
public name: string = "default"
public address: string = "default"
public age: number = 0;
public constructor(init?:Partial<Person>) {
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 }
这为您提供了基本的安全和属性初始化,但这都是可选的,并且可能是无序的。如果不传递字段,则保留类的默认值。
您还可以将其与所需的构造函数参数混合使用——将字段放在末尾。
我认为这和c#风格差不多(实际的field-init语法被拒绝了)。我更喜欢适当的字段初始化器,但看起来还不会发生。
为了比较,如果你使用强制转换方法,你的初始化器对象必须有你要强制转换的类型的所有字段,加上不要得到任何类本身创建的类特定的函数(或派生)。
我更倾向于这样做,使用(可选的)自动属性和默认值。您没有建议这两个字段是数据结构的一部分,所以这就是我选择这种方式的原因。
您可以在类中拥有属性,然后以通常的方式分配它们。显然,他们可能需要,也可能不需要,所以这也是另一回事。只是这是一个很好的语法糖。
class MyClass{
constructor(public Field1:string = "", public Field2:string = "")
{
// other constructor stuff
}
}
var myClass = new MyClass("ASD", "QWE");
alert(myClass.Field1); // voila! statement completion on these properties
这是如何……
function as_<T>(o: T) { return o; };
// ... some code before
return as_<MyClass>({ Field1 = "ASD", Field2 = "QWE" });
// ... some code after
type ExcludeMethods<T> = Pick<T, { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]>;
class MyClass {
public name!: string;
public age!: number;
public optional?: boolean;
private yep: string = "";
constructor(props: ExcludeMethods<typeof MyClass.prototype>) {
Object.assign(this, props);
}
public method() {
}
}
const thing = new MyClass({
name: "bob",
age: 15
});
TS操场