Gets the name of a number, even if it's stupidly big. Supersedes TheoryOfNekomata/number-name.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

60 lines
1.4 KiB

  1. import { enUS } from './systems';
  2. import { StringifySystem } from './common';
  3. type StringifyValue = string | number | bigint;
  4. export interface StringifyOptions {
  5. system?: StringifySystem;
  6. makeGroupOptions?: Record<string, unknown>;
  7. }
  8. export const stringify = (
  9. valueRaw: StringifyValue,
  10. options = {} as StringifyOptions
  11. ): string => {
  12. if (!(['bigint', 'number', 'string'].includes(typeof (valueRaw as unknown)))) {
  13. throw new TypeError('value must be a string, number, or bigint');
  14. }
  15. const value = valueRaw.toString().replace(/\s/g, '');
  16. const { system = enUS, makeGroupOptions} = options;
  17. if (value.startsWith('-')) {
  18. return system.makeNegative(stringify(value.slice(1), options));
  19. }
  20. const groups = system
  21. .group(value)
  22. .map(([group, place]) => (
  23. system.makeGroup(group, place, makeGroupOptions)
  24. ));
  25. return system.finalize(groups);
  26. };
  27. type ParseType = 'string' | 'number' | 'bigint';
  28. export interface ParseOptions {
  29. system?: StringifySystem;
  30. type?: ParseType;
  31. }
  32. export const parse = (value: string, options = {} as ParseOptions) => {
  33. const { system = enUS, type = 'string' } = options;
  34. const tokens = system.tokenize(value);
  35. const groups = system.parseGroups(tokens);
  36. const stringValue = system.combineGroups(groups);
  37. switch (type) {
  38. case 'number':
  39. return Number(stringValue);
  40. case 'bigint':
  41. return BigInt(stringValue);
  42. default:
  43. break;
  44. }
  45. return stringValue;
  46. };