Wie initiiert man eine neue Klasse in TS auf diese Weise (Beispiel in C#, um zu zeigen, was ich will):
// ... some code before
return new MyClass { Field1 = "ASD", Field2 = "QWE" };
// ... some code after
Wie initiiert man eine neue Klasse in TS auf diese Weise (Beispiel in C#, um zu zeigen, was ich will):
// ... some code before
return new MyClass { Field1 = "ASD", Field2 = "QWE" };
// ... some code after
In einigen Fällen kann es akzeptabel sein, Folgendes zu verwenden Object.create
. Die Mozilla-Referenz enthält ein Polyfill, wenn Sie Rückwärtskompatibilität benötigen oder eine eigene Initialisierungsfunktion erstellen möchten.
Angewandt auf Ihr Beispiel:
Object.create(Person.prototype, {
'Field1': { value: 'ASD' },
'Field2': { value: 'QWE' }
});
In meinem Fall fand ich dies in Unit-Tests aus zwei Gründen nützlich:
Unit-Test-Frameworks (wie Jasmine) können den Objektprototyp ( __proto__
) und den Test nicht bestehen. Zum Beispiel:
var actual = new MyClass(); actual.field1 = "ASD"; expect({ field1: "ASD" }).toEqual(actual); // fails
Die Ausgabe des fehlgeschlagenen Einheitstests gibt keinen Aufschluss darüber, was nicht übereinstimmt.
Schließlich wird die unter http://typescript.codeplex.com/workitem/334 unterstützt keine Inline-Deklaration im Json-Stil. Das folgende Beispiel lässt sich nicht kompilieren:
var o = {
m: MyClass: { Field1:"ASD" }
};
Ich wollte eine Lösung, die Folgendes bietet:
Ich mache es folgendermaßen:
export class Person {
id!: number;
firstName!: string;
lastName!: string;
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
constructor(data: OnlyData<Person>) {
Object.assign(this, data);
}
}
const person = new Person({ id: 5, firstName: "John", lastName: "Doe" });
person.getFullName();
Alle Eigenschaften im Konstruktor sind obligatorisch und dürfen nicht weggelassen werden, ohne dass ein Compilerfehler auftritt.
Sie ist abhängig von der OnlyData
die herausfiltert getFullName()
aus den erforderlichen Eigenschaften und ist wie folgt definiert:
// based on : https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c
type FilterFlags<Base, Condition> = { [Key in keyof Base]: Base[Key] extends Condition ? never : Key };
type AllowedNames<Base, Condition> = FilterFlags<Base, Condition>[keyof Base];
type SubType<Base, Condition> = Pick<Base, AllowedNames<Base, Condition>>;
type OnlyData<T> = SubType<T, (_: any) => any>;
Die derzeitigen Grenzen dieser Methode:
Ich würde eher dazu tendieren, es auf diese Weise zu machen, mit (optionalen) automatischen Eigenschaften und Standardwerten. Sie haben nicht vorgeschlagen, dass die beiden Felder Teil einer Datenstruktur sind, deshalb habe ich diesen Weg gewählt.
Sie könnten die Eigenschaften der Klasse haben und sie dann auf die übliche Weise zuweisen. Und natürlich können sie erforderlich sein oder auch nicht, also ist das auch etwas anderes. Es ist nur so, dass dies ein schöner syntaktischer Zucker ist.
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
Sie könnten eine Klasse mit optionalen Feldern (markiert mit ?) und einen Konstruktor haben, der eine Instanz derselben Klasse erhält.
class Person {
name: string; // required
address?: string; // optional
age?: number; // optional
constructor(person: Person) {
Object.assign(this, person);
}
}
let persons = [
new Person({ name: "John" }),
new Person({ address: "Earth" }),
new Person({ age: 20, address: "Earth", name: "John" }),
];
In diesem Fall können Sie die Pflichtfelder nicht auslassen. Auf diese Weise können Sie die Konstruktion des Objekts sehr genau steuern.
Sie könnten den Konstruktor mit dem Typ Partial verwenden, wie in anderen Antworten erwähnt:
public constructor(init?:Partial<Person>) {
Object.assign(this, init);
}
Das Problem ist, dass alle Felder optional werden, was in den meisten Fällen nicht wünschenswert ist.
Um eine Klasse zu initiieren, ohne alle Eigenschaften für Standardwerte neu zu deklarieren:
class MyClass{
prop1!: string //required to be passed in
prop2!: string //required to be passed in
prop3 = 'some default'
prop4 = 123
constructor(opts:{prop1:string, prop2:string} & Partial<MyClass>){
Object.assign(this,opts)
}
}
Dies kombiniert einige der bereits ausgezeichneten Antworten
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.