생성자 축약형을 사용할 경우 선택하지 않은 값도 출력됨
export class UserEntity{
name?: string;
age?: number;
marketing?: boolean;
constructor(name?: string, age?: number, marketing?: boolean){
if(name) this.name = name;
if(age) this.age = age;
if(marketing != undefined) this.marketing = marketing;
}
// 아래 방법을 사용할 경우 없는 값도 전부 출력 됨(선택한 값만 출력되는게 아니라 전부 출력됨[undefined도 출력됨])
// constructor(public name: string, public age: number, public marketing: boolean){}
static Builder = class { // Builder 변수에 익명클래스 생성
private _name?: string;
private _age?: number;
private _marketing?: boolean;
// 원래 class 의 필드와 이름이 같음 함수 = 메소드
name(newName: string){
this._name = newName
return this;
}
age(newAge: number){
this._age = newAge > 0 ? newAge : 0;
return this;
}
marketing(newMarketing: boolean){
this._marketing = newMarketing
return this;
}
build(): UserEntity {
return new UserEntity(this._name, this._age, this._marketing)
}
}
}
스프링의 repository처럼 사용
import { UserEntity } from "./builder";
const newUser: UserEntity = new UserEntity.Builder()
.name("danbi")
.age(25)
.marketing(false)
.build();
console.log(newUser)
빌더 모듈 생성
export function Builder<T extends { new (...args: any[]): {} }> (
constructor: T
) {
const keys = Object.keys(new constructor())
return class extends constructor{
static Builder = class {
constructor(){
for(let key of keys){
Object.defineProperties(this, {
["_" + key]: {
value: this[key],
enumerable: true,
writable: true
},
[key]: {
value: (newValue: any) => {
this["_" + key] = newValue
return this
},
enumerable: true
}
})
}
}
build(){
return new constructor(
// 오브젝트 키들 중 _로 시작하는 값을 필터링해 반복문으로 뽑기
...Object.keys(this).filter((e) => (e.startsWith("_") ? true : false)).map(e => this[e])
)
}
}
}
}
빌더데코레이터 선언
import { Builder } from "./deco";
class BuilderInit{
static Builder = class {
build(){}
[props: string]: Function;
}
}
@Builder
export class PostEntity extends BuilderInit{
constructor(public title: string, public content: string, public author: string) {
super()
}
}