Add license information.
[ustaxlib.git] / src / core / Form.ts
1 // Copyright 2020 Blue Static <https://www.bluestatic.org>
2 // This program is free software licensed under the GNU General Public License,
3 // version 3.0. The full text of the license can be found in LICENSE.txt.
4 // SPDX-License-Identifier: GPL-3.0-only
5
6 import Person from './Person';
7 import TaxReturn from './TaxReturn';
8 import { Line } from './Line';
9 import { InconsistencyError, NotFoundError } from './Errors';
10
11 export default abstract class Form<L extends { [key: string]: Line<any> },
12 I = unknown> {
13 abstract readonly name: string;
14
15 protected abstract readonly _lines: L;
16
17 readonly supportsMultipleCopies: boolean = false;
18
19 private readonly _input?: I;
20
21 // Avoid using this; prefer the getLine() helpers declared below. This
22 // is only exposed for propagating line type information.
23 get lines(): L { return this._lines; }
24
25 constructor(input?: I) {
26 this._input = input;
27 }
28
29 init() {
30 for (const id in this._lines) {
31 let l = this._lines[id];
32 l._id = id;
33 l.form = this;
34 }
35 }
36
37 person(): Person | undefined {
38 return undefined;
39 }
40
41 getLine<K extends keyof L>(id: K): L[K] {
42 if (!(id in this._lines))
43 throw new NotFoundError(`Form ${this.name} does not have line ${id}`);
44 return this._lines[id];
45 }
46
47 getValue<K extends keyof L>(tr: TaxReturn, id: K): ReturnType<L[K]['value']> {
48 const line: L[K] = this.getLine(id);
49 return line.value(tr);
50 }
51
52 getInput<K extends keyof I>(name: K): I[K] {
53 if (!(name in this._input)) {
54 throw new NotFoundError(`No input with key ${name} on form ${this.name}`);
55 }
56 return this._input[name];
57 }
58
59 hasInput<K extends keyof I>(name: K): boolean {
60 return this._input !== undefined && name in this._input;
61 }
62 };
63
64 export type FormClass<T extends Form<any>> = new (...args: any[]) => T;
65
66 export function isFormT<T extends Form<any>>(form: Form<any>,
67 formClass: FormClass<T>):
68 form is T {
69 return form.constructor === formClass;
70 }