a-calc
Version:
A very powerful and easy-to-use number precision calculation and formatting library.
241 lines (217 loc) • 9.67 kB
TypeScript
import { U, StrRemoveSome, If_StrIncludes, Or, Equal } from "typescript-treasure";
export type InjectDataFn<Expr> = <const Data>
( fill_data: Data extends string | number | undefined | null ? never : Data ) =>
(
If_HasNumFmt<Expr, Data> extends true ?
number | GetWrapErr<Data>
:
string | GetWrapErr<Data>
);
export type InjectExprFn<Data> = <const Expr>
( expr: Expr extends string | number ? Expr : never ) =>
(
If_HasNumFmt<Expr, Data> extends true ?
number | GetWrapErr<Data>
:
string | GetWrapErr<Data>
);
type If_IncludesVar<T> = U.If_IncludeVar<StrRemoveSome<T, ["!n","!e","!u","!N","!E","!U"]>>;
type If_NumOrStr<T> = T extends string | number ? true : false;
type If_FillData<T> = T extends string | number | undefined | null ? false : true;
type Not<T> = T extends true ? false : true;
type GetWrapErr<T> = T extends { _error: infer I; } ? I : "-";
type GetFmt<T> = T extends { _fmt: infer I; } ? I : never;
type If_HasNumFmt<Expr, Data> =
Or<
If_StrIncludes<Expr, ["!n"]> | If_StrIncludes<GetFmt<Data>, ["!n"]>
>;
type DirectReturn<Expr, Data> =
If_HasNumFmt<Expr, Data> extends true ?
(
number | GetWrapErr<Data>
)
:
(
string | GetWrapErr<Data>
);
type FuncReturn<Arg1> =
If_IncludesVar<Arg1> extends true ?
(
InjectDataFn<Arg1>
)
:
(
If_FillData<Arg1> extends true ?
InjectExprFn<Arg1>
:
never
);
type If_DirectReturn<Arg1, Arg2> =
Or<
If_NumOrStr<Arg1> & If_FillData<Arg2>
|
If_NumOrStr<Arg1> & Not<If_IncludesVar<Arg1>>
>;
type CalcConfig<Fmt extends string, Err> =
any[] | Partial<{
_error: Err,
_fill_data: any,
_unit: boolean,
_fmt: Fmt,
_memo: boolean,
_mode: "space" | "space-all" | "normal", // space 只会影响表达式部分 space_all 也会影响 fmt 部分
[Prop: string]: any;
}>;
export type Calc = <const Expr extends string | number, const Fmt extends string, const Err = never>
( expr: Expr, options?: CalcConfig<Fmt, Err> ) =>
(
If_StrIncludes<Fmt, ["!n"]> & If_StrIncludes<Expr, ["!n"]> extends true ?
number | Err
:
string | Err
);
export interface CalcWrap
{
<const Expr extends string | number>
( expr: Expr ): If_IncludesVar<Expr> extends true ? FuncReturn<Expr> : If_StrIncludes<Expr, ["!n", "!N"]> extends true ? number | "-" : string | "-";
<const Expr extends string | number, const Fmt extends string, const Err, const Options extends CalcConfig<Fmt, Err>>
( expr: Expr, options: Options ): DirectReturn<Expr, Options>;
<const Fmt extends string, const Err, const Options extends CalcConfig<Fmt, Err>>
( options: Options ): FuncReturn<Options>;
}
declare const calc_util: {
/**
* 检查当前库是否有更新版本
*/
check_update(): void;
/**
* 打印当前库的版本
*/
print_version(): void;
};
/**
* 传入字符串算术式或数字返回计算的结果
* @param expr 一个字符串算术式或一个数字
* @param options 一个配置或者用来填充算术式的数据源,或者两者的结合
* @returns 返回进过计算和格式化之后的结果,结果可能是字符串或数字或自定义的错误类型
*
* @example:
* ```typescript
* calc("a + b", {a: 1, b: 2}) // 3
* calc("1.00") // 1
* calc("1.00 | =3") // 1.000
* calc("a + b | =2", {a: 0.1, b: 0.2}) // 0.30
* calc("a++(b", {_error: null}) // null
* calc("1% + 2%", {_unit: true}) // 3%
* ```
*/
export const calc: Calc;
/**
* calc方法的别名.传入字符串算术式或数字返回计算的结果
* @param expr 一个字符串算术式或一个数字
* @param options 一个配置或者用来填充算术式的数据源,或者两者的结合
* @returns 返回进过计算和格式化之后的结果,结果可能是字符串或数字或自定义的错误类型
*/
export const fmt: Calc;
/**
* calc方法的包装版本,除了支持calc所有的功能还额外提供了更强大的类型推导和更灵活的编写方式
* @param expr 一个字符串算术式或一个数字
* @param options 一个配置或者用来填充算术式的数据源,或者两者的结合
* @returns 返回进过计算和格式化之后的结果,结果可能是字符串或数字或自定义的错误类型
*
* @example:
* ```typescript
* // 先传入表达式还是先注入数据源都是可以的
* calc_wrap("a + b")({a: 1, b: 2}) // 3
* calc_wrap("a + b",{a: 1, b: 2}) // 3
* calc_wrap({a: 0.1, b: 0.2})("a + b | =2") // 0.30
* ```
*/
export const calc_wrap: CalcWrap;
declare const version: string;
export const parse_thousands: (str: string) => string;
/**
* 传入两个数字或数字字符串进行相加并返回结果,可以指定第三个参数控制返回数字还是数字字符串
* @param a 一个数字或数字字符串
* @param b 另一个数字或数字字符串
* @param type 输出数字还是字符串
* @returns 计算得到的结果
*/
export const plus: <const T extends "number" | "string" = "number">(a: number|string, b: number|string, type?: T) => T extends "number" ? number : string;
/**
* 传入两个数字或数字字符串进行相减并返回结果,可以指定第三个参数控制返回数字还是数字字符串
* @param a 一个数字或数字字符串
* @param b 另一个数字或数字字符串
* @param type 输出数字还是字符串
* @returns 计算得到的结果
*/
export const sub: <const T extends "number" | "string" = "number">(a: number|string, b: number|string, type?: T) => T extends "number" ? number : string;
/**
* 传入两个数字或数字字符串进行相乘并返回结果,可以指定第三个参数控制返回数字还是数字字符串
* @param a 一个数字或数字字符串
* @param b 另一个数字或数字字符串
* @param type 输出数字还是字符串
* @returns 计算得到的结果
*/
export const mul: <const T extends "number" | "string" = "number">(a: number|string, b: number|string, type?: T) => T extends "number" ? number : string;
/**
* 传入两个数字或数字字符串进行相除并返回结果,可以指定第三个参数控制返回数字还是数字字符串
* @param a 一个数字或数字字符串
* @param b 另一个数字或数字字符串
* @param type 输出数字还是字符串
* @returns 计算得到的结果
*/
export const div: <const T extends "number" | "string" = "number">(a: number|string, b: number|string, type?: T) => T extends "number" ? number : string;
/**
* 传入两个数字或数字字符串进行整除并返回结果,可以指定第三个参数控制返回数字还是数字字符串
* @param a 一个数字或数字字符串
* @param b 另一个数字或数字字符串
* @param type 输出数字还是字符串
* @returns 计算得到的结果
*/
export const idiv: <const T extends "number" | "string" = "number">(a: number|string, b: number|string, type?: T) => T extends "number" ? number : string;
/**
* 传入两个数字或数字字符串进行幂运算并返回结果,可以指定第三个参数控制返回数字还是数字字符串
* @param a 一个数字或数字字符串
* @param b 另一个数字或数字字符串
* @param type 输出数字还是字符串
* @returns 计算得到的结果
*/
export const pow: <const T extends "number" | "string" = "number">(a: number|string, b: number|string, type?: T) => T extends "number" ? number : string;
/**
* 传入两个数字或数字字符串进行取模并返回结果,可以指定第三个参数控制返回数字还是数字字符串
* @param a 一个数字或数字字符串
* @param b 另一个数字或数字字符串
* @param type 输出数字还是字符串
* @returns 计算得到的结果
*/
export const mod: <const T extends "number" | "string" = "number">(a: number|string, b: number|string, type?: T) => T extends "number" ? number : string;
/**
* calc方法的精简版本,去除了对单位计算的支持但是这个方法性能更好一些,该方法永远不会报错,在计算出错的时候返回 -
* @param expr 一个字符串计算式或数字,如果是计算式那么内部的所有单元都需要使用一个空格严格分割
* @param fmt_expr 一个用于描述如何格式化计算结果的字符串表达式
* @param data 用于填充算术式中变量的数据源可以是对象也可以是对象数组
* @param err_value 计算错误时返回的结果,模式是 -
* @returns string | number | Err
*/
export const calc_lite: <const T extends string | null | undefined, const Err = "-">
(calc_expr: string | number, fmt_expr?: T, data?: any, err_value?: Err) =>
(
Or<Equal<T, null> | Equal<T, undefined>> extends true ?
( string | Err )
:
(
If_StrIncludes<T, ["!n"]> extends true ?
number | Err
:
string | Err
)
)
/**
* 较为原始的计算方法,使用中缀表达式的顺序来传入参数
* @param value1 计算数1
* @param op "+" | "-" | "*" | "/" | "%" | "**" | "//"
* @param value2 计算数2
* @returns 计算结果
*/
export const calc_mini: (value1: number | string, op: "+" | "-" | "*" | "/" | "%" | "**" | "//", value2: number | string) => string