Make Form input strongly typed with generics.
authorRobert Sesek <rsesek@bluestatic.org>
Wed, 19 Feb 2020 01:32:53 +0000 (20:32 -0500)
committerRobert Sesek <rsesek@bluestatic.org>
Wed, 19 Feb 2020 01:32:53 +0000 (20:32 -0500)
src/Form.test.ts
src/Form.ts

index 795fd850fab9dac7c210eab37aed3866f81853e2..b7c3d0eb6703844ed74b162839f00b5a508ef80e 100644 (file)
@@ -71,12 +71,16 @@ test('add line to two forms', () => {
 });
 
 test('input', () => {
-  class TestForm extends Form {
+  interface TestInput {
+    filingStatus: string;
+    money: number;
+  };
+  class TestForm extends Form<TestInput> {
     get name() { return '1040'; }
 
     protected getLines() { return []; }
   };
-  const f = new TestForm({ 'Filing Status': 'S' });
-  expect(f.getInput('Filing Status')).toBe('S');
-  expect(() => f.getInput('Unknown')).toThrow(NotFoundError);
+
+  const f = new TestForm({ filingStatus: 'S', money: 100.0 });
+  expect(f.getInput('filingStatus')).toBe('S');
 });
index e63829454d43f7694e57f12b2dacd9b786a059fa..507a6112e1a75d2b96bc93294998125013abf566 100644 (file)
@@ -1,13 +1,13 @@
 import { Line } from './Line';
 import { InconsistencyError, NotFoundError } from './Errors';
 
-export default abstract class Form {
+export default abstract class Form<I = unknown> {
   private _lines: Line<any>[] = [];
-  private _input?: object;
+  private _input?: I;
 
   abstract get name(): string;
 
-  constructor(input?: object) {
+  constructor(input?: I) {
     this._input = input;
     this.getLines().map(this.addLine.bind(this));
   }
@@ -40,10 +40,10 @@ export default abstract class Form {
     return lines[0];
   }
 
-  getInput<T>(name: string): T {
+  getInput<K extends keyof I>(name: K): I[K] {
     if (!(name in this._input)) {
       throw new NotFoundError(`No input with key ${name} on form ${this.name}`);
     }
-    return this._input[name] as T;
+    return this._input[name];
   }
 };