Skip to content

Commit

Permalink
feat(primitives): implement decimal type
Browse files Browse the repository at this point in the history
  • Loading branch information
tangdrew committed Jan 21, 2019
1 parent 97fec4a commit 06636a6
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 2 deletions.
2 changes: 2 additions & 0 deletions packages/primitives/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
"test": "jest"
},
"devDependencies": {
"@types/big.js": "^4.0.5",
"typescript": "^3.2.2"
},
"dependencies": {
"big.js": "^5.2.2",
"fp-ts": "^1.12.3",
"io-ts": "^1.5.2"
},
Expand Down
59 changes: 59 additions & 0 deletions packages/primitives/src/decimal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Decimal FHIR Primitive Runtime Type
*/

import { Big } from "big.js";
import { Type, success, failure } from "io-ts";

/**
* Class that wraps big.js to maintain precision, including trailing zeros
*/
export class Decimal extends Big {
private dp: number;
constructor(n) {
super(n);
this.dp = this.decimalPlaces(n);
}

public toFixed(dp?: number) {
return super.toFixed(this.dp);
}

private decimalPlaces(n: string | number) {
// Coerce to string
const number = String(n);
const hasDecimal = number.includes(".");
const exponentialForm = number.includes("e");
if (hasDecimal) {
if (exponentialForm) {
const [mantissa, exponent] = number.split(".")[1].split("e");
return mantissa.length - parseInt(exponent);
} else {
return number.split(".")[1].length;
}
} else {
return 0;
}
}
}

export class DecimalType extends Type<Decimal, string, unknown> {
readonly _tag: "DecimalType" = "DecimalType";
constructor() {
super(
"decimal",
(m): m is Decimal => m instanceof Decimal,
(m, c) => {
try {
const decimal = new Decimal(<any>m);
return success(decimal);
} catch (e) {
return failure(m, c);
}
},
a => a.toFixed()
);
}
}

export const decimal = new DecimalType();
12 changes: 11 additions & 1 deletion packages/primitives/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@
*/

import { BooleanType, boolean } from "./boolean";
import { DecimalType, decimal } from "./decimal";
import { IntegerType, integer } from "./integer";
import { StringType, string } from "./string";

export { BooleanType, boolean, IntegerType, integer, StringType, string };
export {
boolean,
BooleanType,
decimal,
DecimalType,
integer,
IntegerType,
string,
StringType
};
40 changes: 40 additions & 0 deletions packages/primitives/test/decimal.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Tests for Decimal Runtime Type
*/

import { assertSuccess, assertFailure } from "./helpers";
import { decimal } from "../src";
import { Decimal } from "../src/decimal";

describe("DecimalType", () => {
it("should succeed validating a valid value", () => {
const T = decimal;
const input = "1.01";
const value = new Decimal(input);
assertSuccess(T.decode(input));
expect(T.decode(input).value).toEqual(value);
});

it("should successfully maintain precision", () => {
const T = decimal;
expect(T.decode("1.0100").map(T.encode).value).toEqual("1.0100");
expect(T.decode(1.01).map(T.encode).value).toEqual("1.01");
expect(T.decode("1.01e2").map(T.encode).value).toEqual("101");
expect(T.decode("1.0100e2").map(T.encode).value).toEqual("101.00");
});

it("should fail validating an invalid value", () => {
const T = decimal;
assertFailure(T.decode("abc"), [
'Invalid value "abc" supplied to : decimal'
]);
});

it("should type guard", () => {
const T = decimal;
const value = new Decimal("1.010");
expect(T.is(value)).toEqual(true);
expect(T.is("b")).toEqual(false);
expect(T.is(undefined)).toEqual(false);
});
});
19 changes: 18 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,11 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==

"@types/big.js@^4.0.5":
version "4.0.5"
resolved "https://registry.yarnpkg.com/@types/big.js/-/big.js-4.0.5.tgz#62c61697646269e39191f24e55e8272f05f21fc0"
integrity sha512-D9KFrAt05FDSqLo7PU9TDHfDgkarlwdkuwFsg7Zm4xl62tTNaz+zN+Tkcdx2wGLBbSMf8BnoMhOVeUGUaJfLKg==

"@types/events@*":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86"
Expand Down Expand Up @@ -1111,6 +1116,11 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"

big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==

bin-links@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.2.tgz#fb74bd54bae6b7befc6c6221f25322ac830d9757"
Expand Down Expand Up @@ -2184,6 +2194,13 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"

"fhir-ts-codegen@file:packages/fhir-ts-codegen":
version "0.0.6"
dependencies:
clime "^0.5.9"
glob "^7.1.3"
ts-simple-ast "^14.4.2"

figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
Expand Down Expand Up @@ -5997,7 +6014,7 @@ tslint-config-prettier@^1.15.0:
resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.17.0.tgz#946ed6117f98f3659a65848279156d87628c33dc"
integrity sha512-NKWNkThwqE4Snn4Cm6SZB7lV5RMDDFsBwz6fWUkTxOKGjMx8ycOHnjIbhn7dZd5XmssW3CwqUjlANR6EhP9YQw==

tslint@^5.11.0, tslint@^5.12.1:
tslint@^5.11.0:
version "5.12.1"
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.12.1.tgz#8cec9d454cf8a1de9b0a26d7bdbad6de362e52c1"
integrity sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==
Expand Down

0 comments on commit 06636a6

Please sign in to comment.