Make SupportsMultipleCopies an interface.
[ustaxlib.git] / src / Form.ts
1 import { Line } from './Line';
2 import { InconsistencyError, NotFoundError } from './Errors';
3
4 export default abstract class Form<I = unknown> {
5 private _lines: Line<any>[] = [];
6 private _input?: I;
7
8 abstract get name(): string;
9
10 constructor(input?: I) {
11 this._input = input;
12 this.getLines().map(this.addLine.bind(this));
13 }
14
15 protected abstract getLines(): Line<any>[];
16
17 private addLine(line: Line<any>) {
18 if (line.form !== undefined) {
19 throw new InconsistencyError('Line is already in a Form');
20 }
21 try {
22 this.getLine(line.id);
23 } catch {
24 line.form = this;
25 this._lines.push(line);
26 return;
27 }
28 throw new InconsistencyError('Cannot add a line with a duplicate identifier');
29 }
30
31 getLine(id: string): Line<any> {
32 const lines = this._lines.filter(l => l.id === id);
33 if (lines.length == 0) {
34 throw new NotFoundError(id);
35 }
36 return lines[0];
37 }
38
39 getInput<K extends keyof I>(name: K): I[K] {
40 if (!(name in this._input)) {
41 throw new NotFoundError(`No input with key ${name} on form ${this.name}`);
42 }
43 return this._input[name];
44 }
45 };
46
47 export interface SupportsMultipleCopies extends Form {
48 aggregate(forms: Form[]): this;
49 };
50
51 export function supportsMultipleCopies(f: object): f is SupportsMultipleCopies {
52 return f instanceof Form && 'aggregate' in f;
53 };