Skip to content

Instantly share code, notes, and snippets.

@nyaocat
Created November 30, 2020 10:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nyaocat/beddcaabdc1e573dbcd89402bf298f00 to your computer and use it in GitHub Desktop.
Save nyaocat/beddcaabdc1e573dbcd89402bf298f00 to your computer and use it in GitHub Desktop.
Typescriptでタイプセーフなビルダーパターン
type WidthDefined = {width: number};
type HeightDefined = {height:number};
type TitleDefined = {title:string};
type AllDefined = WidthDefined & HeightDefined & TitleDefined;
class WidgetBuilder<T>{
constructor(private params: T){}
width<D>(this:WidgetBuilder<D extends WidthDefined ? never : D>, width: number):WidgetBuilder<D & WidthDefined> {
return new WidgetBuilder(Object.assign(this.params, {width}));
}
height<D>(this:WidgetBuilder<D extends HeightDefined ? never : D>, height: number):WidgetBuilder<D & HeightDefined> {
return new WidgetBuilder(Object.assign(this.params, {height}));
}
title<D>(this:WidgetBuilder<D extends TitleDefined ? never : D>, title: string):WidgetBuilder<D & TitleDefined> {
return new WidgetBuilder(Object.assign(this.params, {title}));
}
build(this:WidgetBuilder<AllDefined>): Widget {
return new Widget(this.params.width, this.params.height, this.params.title);
}
}
class Widget {
public constructor(
private width: number,
private height: number,
private title: string){
}
public static builder():WidgetBuilder<object> {return new WidgetBuilder({});}
}
// OK
Widget.builder()
.width(320)
.height(240)
.title("po")
.build();
// エラー
Widget.builder()
.width(320)
.build();
// エラー
Widget.builder()
.width(320)
.height(240)
.title("po")
.height(480)
.build();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment