因此,我正在尝试在我阅读的打字稿中实现“选项对象”,以替代Java Builder模式。
我看到我可以使用生成器,但是实现起来似乎比“选项对象”要复杂得多,后者以更少的代码提供了类似的东西。
这是我想要实现的目标:
class OptionsObject {
private readonly name : string;
private readonly no? : number;
constructor(o : OptionsObject){
this.name = o.name;
this.no = o.no;
}
uradi() : void{
console.log(`Number is ${this.no} and name is ${this.name}`);
}
}
const p = new OptionsObject({
name:"asd",
no:11
} as unknown as OptionsObject); //works but no type-safety
p.uradi();
//standard java builder
//const p2 = new OptionsObjectBuilder().name("asd").no(11).build();
我只想将所需的属性传递给new OptionsObject
。现在就这样-有效,但是我没有类型安全性。我不想引入其他interface
,因为那样的话,我将需要重复属性。
有没有更好的方法来实现类型安全,还是有其他类似于生成器的模式适合打字稿?
答案 0 :(得分:0)
对于Typescript实用程序类型Partial<T>
documentation中的示例
interface Todo {
title: string;
description: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
return { ...todo, ...fieldsToUpdate };
}
const todo1 = {
title: 'organize desk',
description: 'clear clutter',
};
const todo2 = updateTodo(todo1, {
description: 'throw out trash',
});
答案 1 :(得分:0)
在您的情况下,您要告诉Typescript构造函数接受class<OptionsObject>
类型的对象。
OptionsObject
不是普通的javascript对象,就像您要传递的对象一样。
关于此:
我不想引入其他接口,因为那样我就需要重复属性。
您实际上并不是在复制属性,而是在定义合同。如果您不熟悉composition
设计模式,那么有几本介绍它的书,包括Head First设计模式和Clean Architecture,您都可以在选择的阅读平台上找到它们。
但是要回答您的问题:
实现所需目标的唯一方法是使用接口。我在下面有一个示例,但是从技术上讲,您将没有来实现该接口,并且可以将其用作参数的类型。通过实现接口,私有成员变量必须变为公共,因为接口成员始终是公共的。
interface OptionsObject {
readonly name: string;
readonly no?: number;
}
class OptionsObjectImpl implements OptionsObject {
readonly name: string; // cannot be private due to being part of the interface
readonly no: number;
constructor(o : OptionsObject){
this.name = o.name;
this.no = o.no;
}
uradi() : void{
console.log(`Number is ${this.no} and name is ${this.name}`);
}
}
const p = new OptionsObjectImpl({
name:"asd",
no:11
}); //works with type-safety
p.uradi();
希望这会有所帮助。
编辑:添加而无需执行。
interface OptionsObjectInterface {
readonly name: string;
readonly no?: number;
}
class OptionsObject {
private readonly name: string; // cannot be private due to being part of the interface
private readonly no: number;
constructor(o : OptionsObjectInterface){
this.name = o.name;
this.no = o.no;
}
uradi() : void{
console.log(`Number is ${this.no} and name is ${this.name}`);
}
}
const p = new OptionsObject({
name:"asd",
no:11
}); //works with type-safety
p.uradi();
答案 2 :(得分:0)
如果我们看一下 Builder Pattern 的概念,我们会看到几个简单的东西组成的方法:
因此,TypeScript 方法的所有不同之处在于我们使用 普通 javascript 对象作为构建器对象,因为我们不需要像在爪哇。但是我们仍然需要类型安全,所以我们只需要定义一个构建器对象的类型。
此外,我们将实现我们的“build”方法作为主对象类的静态方法。
这就是我们得到的:
class MyObject {
private constructor(readonly prop1: string, readonly prop2: number) {
}
// an alternative to the 'build' method
static createInstance(builder: MyObjectBuilder): MyObject {
// some validation...
return new MyObject(builder.prop1, builder.prop2);
}
}
// We make all props optional to allow specify
// them at any moment as if it would be a builder
type MyObjectBuilder = {
prop1?: string,
prop2?: number
};
用法:
let builder: MyObjectBuilder = {};
builder.prop1 = 'text';
builder.prop2 = 7;
let myObject = MyObject.createInstance(builder);
当然,在某些情况下,将 builder 直接传递给我们类的公共构造函数就足够了,但它不能完全替代 Builder Pattern,因为它不仅提供了一种将选项传递给我们的方法一个对象构造函数,但也让我们可以完全控制对象的构建(在比对象本身级别更高的级别上)。