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