@zwa73/utils 1.0.75 → 1.0.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/UtilCom.js +2 -3
- package/dist/UtilFP.js +2 -0
- package/dist/UtilFileTools.js +2 -2
- package/dist/UtilFunctions.d.ts +37 -3
- package/dist/UtilFunctions.js +77 -19
- package/dist/UtilInterfaces.d.ts +39 -12
- package/dist/UtilInterfaces.js +0 -12
- package/dist/test/composeTest.js +7 -0
- package/package.json +1 -1
- package/src/UtilCom.ts +3 -3
- package/src/UtilFP.ts +5 -0
- package/src/UtilFileTools.ts +3 -2
- package/src/UtilFunctions.ts +84 -25
- package/src/UtilInterfaces.ts +52 -16
- package/src/test/composeTest.ts +41 -0
package/dist/UtilCom.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UtilCom = void 0;
|
|
4
|
-
const UtilInterfaces_1 = require("./UtilInterfaces");
|
|
5
4
|
const https = require("https");
|
|
6
5
|
const http = require("http");
|
|
7
6
|
const UtilLogger_1 = require("./UtilLogger");
|
|
@@ -21,7 +20,7 @@ var UtilCom;
|
|
|
21
20
|
const hasTimeLimit = (timeLimit >= 10);
|
|
22
21
|
if (hasTimeLimit)
|
|
23
22
|
timeLimit *= 1000;
|
|
24
|
-
const jsonStr =
|
|
23
|
+
const jsonStr = UtilFunctions_1.UtilFunc.stringifyJToken(json);
|
|
25
24
|
const funcName = `s${posttype}Psot`;
|
|
26
25
|
return new Promise((resolve, rejecte) => {
|
|
27
26
|
const resFunc = (res) => {
|
|
@@ -51,7 +50,7 @@ var UtilCom;
|
|
|
51
50
|
}
|
|
52
51
|
try {
|
|
53
52
|
let obj = JSON.parse(resdata);
|
|
54
|
-
UtilLogger_1.SLogger.http(funcName + " 接受信息:",
|
|
53
|
+
UtilLogger_1.SLogger.http(funcName + " 接受信息:", UtilFunctions_1.UtilFunc.stringifyJToken(obj));
|
|
55
54
|
resolve(obj);
|
|
56
55
|
return;
|
|
57
56
|
}
|
package/dist/UtilFP.js
CHANGED
|
@@ -16,12 +16,14 @@ var UtilFP;
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
UtilFP.curry = curry;
|
|
19
|
+
//#endregion
|
|
19
20
|
function flow(...fs) {
|
|
20
21
|
return (arg) => {
|
|
21
22
|
return fs.reduce((value, func) => func(value), arg);
|
|
22
23
|
};
|
|
23
24
|
}
|
|
24
25
|
UtilFP.flow = flow;
|
|
26
|
+
//#endregion
|
|
25
27
|
function pipe(input, ...fs) {
|
|
26
28
|
return fs.reduce((value, func) => func(value), input);
|
|
27
29
|
}
|
package/dist/UtilFileTools.js
CHANGED
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.UtilFT = void 0;
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const path = require("path");
|
|
6
|
-
const UtilInterfaces_1 = require("./UtilInterfaces");
|
|
7
6
|
const UtilLogger_1 = require("./UtilLogger");
|
|
8
7
|
const JSON5 = require("json5");
|
|
9
8
|
const glob_1 = require("glob");
|
|
9
|
+
const UtilFunctions_1 = require("./UtilFunctions");
|
|
10
10
|
/**文件工具 */
|
|
11
11
|
var UtilFT;
|
|
12
12
|
(function (UtilFT) {
|
|
@@ -149,7 +149,7 @@ var UtilFT;
|
|
|
149
149
|
* @param token - 所要写入的JToken
|
|
150
150
|
*/
|
|
151
151
|
async function writeJSONFile(filePath, token) {
|
|
152
|
-
let str =
|
|
152
|
+
let str = UtilFunctions_1.UtilFunc.stringifyJToken(token);
|
|
153
153
|
if (path.extname(filePath) !== '.json')
|
|
154
154
|
filePath += '.json';
|
|
155
155
|
// 判断文件路径是否存在 不存在则创建
|
package/dist/UtilFunctions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComposedClass, ComposedMixinable, JToken, Mixinable,
|
|
1
|
+
import { ComposedClass, ComposedMixinable, ExtractOutcome, IJData, JObject, JToken, Mixinable, Outcome, PromiseVerifyFn } from "./UtilInterfaces";
|
|
2
2
|
/**常用函数 */
|
|
3
3
|
export declare namespace UtilFunc {
|
|
4
4
|
/**获取当前时间戳
|
|
@@ -13,6 +13,14 @@ export declare namespace UtilFunc {
|
|
|
13
13
|
* @returns 最终值
|
|
14
14
|
*/
|
|
15
15
|
function initField<T extends object, K extends keyof T>(obj: T, field: K, defaultVal: T[K]): T[K];
|
|
16
|
+
/**初始化一个数据对象
|
|
17
|
+
* @param obj - 目标对象
|
|
18
|
+
* @param checkObj - 用于检测的对象 在对应key缺失时赋予对应值 如果值为函数, 则赋予执行结果 如果结果为 undefined 则不赋值
|
|
19
|
+
* @returns 完成初始化的对象
|
|
20
|
+
*/
|
|
21
|
+
function initObject<T extends JObject>(obj: T, checkObj: {
|
|
22
|
+
[P in keyof T]: T[P] | (() => void | T[P]);
|
|
23
|
+
}): any;
|
|
16
24
|
/**生成一串uuid
|
|
17
25
|
* @returns uuid
|
|
18
26
|
*/
|
|
@@ -54,9 +62,9 @@ export declare namespace UtilFunc {
|
|
|
54
62
|
* @param verifyFn - 验证函数
|
|
55
63
|
* @param repeatCount - 重试次数
|
|
56
64
|
* @param repeatTime - 超时时间/秒 最小为10秒
|
|
57
|
-
* @returns
|
|
65
|
+
* @returns 结果 null 为全部失败/超时
|
|
58
66
|
*/
|
|
59
|
-
function repeatPromise<T>(procFn:
|
|
67
|
+
function repeatPromise<T>(procFn: () => Promise<T>, verifyFn?: PromiseVerifyFn<T>, repeatCount?: number, repeatTime?: number): Promise<T | null>;
|
|
60
68
|
/**部分类组合
|
|
61
69
|
* 将mixin的部分字段混入base
|
|
62
70
|
* @param base - 基础类
|
|
@@ -75,4 +83,30 @@ export declare namespace UtilFunc {
|
|
|
75
83
|
* @returns - 一个新的对象,它的属性是原对象的属性经过映射函数处理后的结果
|
|
76
84
|
*/
|
|
77
85
|
function mapEntries<T extends Object>(obj: T, mapper: (key: keyof T, value: T[keyof T]) => T[keyof T]): T;
|
|
86
|
+
/**处理联合 Outcome
|
|
87
|
+
* @param t - 目标值
|
|
88
|
+
* @param procObj - 所有可能的id组成的处理函数映射
|
|
89
|
+
* @returns 任意处理函数的返回值
|
|
90
|
+
*/
|
|
91
|
+
function matchOutcome<T extends Outcome<string, unknown>, P extends {
|
|
92
|
+
[K in T['status']]: (k: K, v: ExtractOutcome<T, K>['result']) => unknown;
|
|
93
|
+
}>(t: T, procObj: P): {
|
|
94
|
+
[K in keyof P]: ReturnType<P[K]>;
|
|
95
|
+
}[keyof P];
|
|
96
|
+
/**处理联合 字符串
|
|
97
|
+
* @param t - 目标值
|
|
98
|
+
* @param procObj - 所有可能的id组成的处理函数映射
|
|
99
|
+
* @returns 任意处理函数的返回值
|
|
100
|
+
*/
|
|
101
|
+
function matchStr<T extends string, P extends {
|
|
102
|
+
[K in T]: (k: K) => unknown;
|
|
103
|
+
}>(t: T, procObj: P): {
|
|
104
|
+
[K in keyof P]: ReturnType<P[K]>;
|
|
105
|
+
}[keyof P];
|
|
106
|
+
/**将JToken转换为字符串
|
|
107
|
+
* @param token - 待转换的Token
|
|
108
|
+
* @param space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
109
|
+
* @returns 转换完成的字符串
|
|
110
|
+
*/
|
|
111
|
+
function stringifyJToken(token: JToken | IJData, space?: string | number | null | undefined): string;
|
|
78
112
|
}
|
package/dist/UtilFunctions.js
CHANGED
|
@@ -27,6 +27,28 @@ var UtilFunc;
|
|
|
27
27
|
return obj[field];
|
|
28
28
|
}
|
|
29
29
|
UtilFunc.initField = initField;
|
|
30
|
+
/**初始化一个数据对象
|
|
31
|
+
* @param obj - 目标对象
|
|
32
|
+
* @param checkObj - 用于检测的对象 在对应key缺失时赋予对应值 如果值为函数, 则赋予执行结果 如果结果为 undefined 则不赋值
|
|
33
|
+
* @returns 完成初始化的对象
|
|
34
|
+
*/
|
|
35
|
+
function initObject(obj, checkObj) {
|
|
36
|
+
const fixobj = obj;
|
|
37
|
+
for (const key in checkObj) {
|
|
38
|
+
if (obj[key] !== undefined)
|
|
39
|
+
continue;
|
|
40
|
+
const checkVal = checkObj[key];
|
|
41
|
+
if (typeof checkVal === "function") {
|
|
42
|
+
const val = checkVal();
|
|
43
|
+
if (val !== undefined)
|
|
44
|
+
fixobj[key] = val;
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
fixobj[key] = checkVal;
|
|
48
|
+
}
|
|
49
|
+
return fixobj;
|
|
50
|
+
}
|
|
51
|
+
UtilFunc.initObject = initObject;
|
|
30
52
|
/**生成一串uuid
|
|
31
53
|
* @returns uuid
|
|
32
54
|
*/
|
|
@@ -103,71 +125,76 @@ var UtilFunc;
|
|
|
103
125
|
* @param verifyFn - 验证函数
|
|
104
126
|
* @param repeatCount - 重试次数
|
|
105
127
|
* @param repeatTime - 超时时间/秒 最小为10秒
|
|
106
|
-
* @returns
|
|
128
|
+
* @returns 结果 null 为全部失败/超时
|
|
107
129
|
*/
|
|
108
130
|
async function repeatPromise(procFn, verifyFn, repeatCount = 3, repeatTime = 180) {
|
|
109
131
|
//计时
|
|
110
132
|
const timeflag = "repeatPromise " + UtilFunc.genUUID();
|
|
111
133
|
UtilLogger_1.SLogger.time(timeflag);
|
|
112
|
-
|
|
134
|
+
/**是否含有超时时间 */
|
|
113
135
|
const hasRepeatTime = (repeatTime >= 10);
|
|
136
|
+
//转换为毫秒
|
|
114
137
|
if (hasRepeatTime)
|
|
115
138
|
repeatTime *= 1000;
|
|
116
139
|
//验证处理函数
|
|
117
140
|
if (verifyFn === undefined)
|
|
118
141
|
verifyFn = () => "Completed";
|
|
119
|
-
|
|
142
|
+
/**计时器 */
|
|
120
143
|
let timer = null;
|
|
144
|
+
/**计时器 Promise */
|
|
121
145
|
let timerP = null;
|
|
146
|
+
/**计时器 Promise 的返回函数 */
|
|
122
147
|
let resolveFn = null;
|
|
123
148
|
/**清理计时器 */
|
|
124
149
|
const clearTimer = () => {
|
|
125
|
-
if (timer
|
|
150
|
+
if (timer)
|
|
126
151
|
clearInterval(timer);
|
|
127
|
-
if (resolveFn
|
|
152
|
+
if (resolveFn)
|
|
128
153
|
resolveFn("Timeout");
|
|
129
|
-
timerP = null;
|
|
130
|
-
timer = null;
|
|
131
|
-
resolveFn = null;
|
|
154
|
+
timerP = timer = resolveFn = null;
|
|
132
155
|
};
|
|
133
156
|
//进行中的请求
|
|
134
157
|
const plist = [];
|
|
135
158
|
//开始处理
|
|
136
159
|
try {
|
|
160
|
+
//根据最大重试次数限制进行循环
|
|
137
161
|
for (let i = 0; i < repeatCount;) {
|
|
138
162
|
UtilLogger_1.SLogger.info(`开始第 ${i + 1} 次 repeatPromise`);
|
|
139
|
-
|
|
163
|
+
//如果 plist 中当前下标的任务还未创建 则 创建当前任务
|
|
140
164
|
if (plist.length < i + 1) {
|
|
141
165
|
plist.push(procFn().then(result => ({ result, stat: verifyFn(result), index: i })));
|
|
142
166
|
}
|
|
143
167
|
//创建定时器
|
|
144
168
|
if (timerP == null) {
|
|
145
|
-
timerP = new Promise(
|
|
169
|
+
timerP = new Promise((resolve, rejecte) => {
|
|
146
170
|
resolveFn = resolve;
|
|
147
171
|
timer = setTimeout(() => resolve("Timeout"), hasRepeatTime ? repeatTime : Infinity); //无限制则无限时间
|
|
148
172
|
});
|
|
149
173
|
}
|
|
150
|
-
|
|
174
|
+
//等待任意任务 或当前计时器完成
|
|
151
175
|
const currObj = await Promise.race([...plist, timerP]);
|
|
152
176
|
//超时处理
|
|
153
|
-
if (currObj
|
|
177
|
+
if (currObj === "Timeout") {
|
|
154
178
|
UtilLogger_1.SLogger.warn(`第 ${i + 1} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
|
|
155
179
|
clearTimer();
|
|
156
180
|
i++;
|
|
157
181
|
continue;
|
|
158
182
|
}
|
|
183
|
+
//路由请求状态
|
|
159
184
|
const poststat = await currObj.stat;
|
|
160
|
-
|
|
161
|
-
|
|
185
|
+
const result = matchStr(poststat, {
|
|
186
|
+
Completed() {
|
|
162
187
|
UtilLogger_1.SLogger.info(`第 ${currObj.index + 1} 次 repeatPromise 成功`);
|
|
163
188
|
//非当前
|
|
164
189
|
if (currObj.index != i)
|
|
165
190
|
UtilLogger_1.SLogger.info(`成功的 promise 非当前 promise 考虑增大重试间隔\n当前index: ${i}\n当前间隔: ${repeatTime}`);
|
|
166
191
|
return currObj.result;
|
|
167
|
-
|
|
192
|
+
},
|
|
193
|
+
Terminated() {
|
|
168
194
|
UtilLogger_1.SLogger.warn(`第 ${currObj.index + 1} 次 repeatPromise 终止 停止重试`);
|
|
169
195
|
return currObj.result;
|
|
170
|
-
|
|
196
|
+
},
|
|
197
|
+
Failed() {
|
|
171
198
|
//抛弃失败
|
|
172
199
|
plist[currObj.index] = UtilFunc.getNeverResolvedPromise();
|
|
173
200
|
//是当前
|
|
@@ -175,12 +202,14 @@ var UtilFunc;
|
|
|
175
202
|
UtilLogger_1.SLogger.warn(`第 ${currObj.index + 1} 次 repeatPromise 失败 开始重试`);
|
|
176
203
|
clearTimer();
|
|
177
204
|
i++;
|
|
178
|
-
|
|
205
|
+
return;
|
|
179
206
|
}
|
|
180
207
|
//非当前
|
|
181
208
|
UtilLogger_1.SLogger.warn(`第 ${currObj.index + 1} 次 repeatPromise 失败`);
|
|
182
|
-
|
|
183
|
-
}
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
if (result !== undefined)
|
|
212
|
+
return result;
|
|
184
213
|
}
|
|
185
214
|
//全部失败或超时则返回null
|
|
186
215
|
UtilLogger_1.SLogger.warn(`${repeatCount} 次 repeatPromise 尝试均失败`);
|
|
@@ -269,4 +298,33 @@ var UtilFunc;
|
|
|
269
298
|
}, {});
|
|
270
299
|
}
|
|
271
300
|
UtilFunc.mapEntries = mapEntries;
|
|
301
|
+
/**处理联合 Outcome
|
|
302
|
+
* @param t - 目标值
|
|
303
|
+
* @param procObj - 所有可能的id组成的处理函数映射
|
|
304
|
+
* @returns 任意处理函数的返回值
|
|
305
|
+
*/
|
|
306
|
+
function matchOutcome(t, procObj) {
|
|
307
|
+
return procObj[t.status](t.status, t?.result);
|
|
308
|
+
}
|
|
309
|
+
UtilFunc.matchOutcome = matchOutcome;
|
|
310
|
+
/**处理联合 字符串
|
|
311
|
+
* @param t - 目标值
|
|
312
|
+
* @param procObj - 所有可能的id组成的处理函数映射
|
|
313
|
+
* @returns 任意处理函数的返回值
|
|
314
|
+
*/
|
|
315
|
+
function matchStr(t, procObj) {
|
|
316
|
+
return procObj[t](t);
|
|
317
|
+
}
|
|
318
|
+
UtilFunc.matchStr = matchStr;
|
|
319
|
+
/**将JToken转换为字符串
|
|
320
|
+
* @param token - 待转换的Token
|
|
321
|
+
* @param space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
322
|
+
* @returns 转换完成的字符串
|
|
323
|
+
*/
|
|
324
|
+
function stringifyJToken(token, space = "\t") {
|
|
325
|
+
if (space == null)
|
|
326
|
+
space = undefined;
|
|
327
|
+
return JSON.stringify(token, null, space);
|
|
328
|
+
}
|
|
329
|
+
UtilFunc.stringifyJToken = stringifyJToken;
|
|
272
330
|
})(UtilFunc = exports.UtilFunc || (exports.UtilFunc = {}));
|
package/dist/UtilInterfaces.d.ts
CHANGED
|
@@ -14,12 +14,6 @@ export interface IJData {
|
|
|
14
14
|
*/
|
|
15
15
|
toJSON(): JToken;
|
|
16
16
|
}
|
|
17
|
-
/**将JToken转换为字符串
|
|
18
|
-
* @param token - 待转换的Token
|
|
19
|
-
* @param space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
20
|
-
* @returns 转换完成的字符串
|
|
21
|
-
*/
|
|
22
|
-
export declare function stringifyJToken(token: JToken | IJData, space?: string | number | null | undefined): string;
|
|
23
17
|
/**转为可写的 */
|
|
24
18
|
export type Writeable<T> = {
|
|
25
19
|
-readonly [P in keyof T]: T[P];
|
|
@@ -55,24 +49,23 @@ export type ExclusiveRecord<B, T, K extends string[], TMP = ExclusiveRecursive<B
|
|
|
55
49
|
/**符合JObject约束的互斥表 */
|
|
56
50
|
export type ExclusiveJObject<B extends JObject, T extends JToken, K extends string[], TMP extends JArray = ExclusiveRecursive<B, T, K>> = TMP[number];
|
|
57
51
|
/**请求完成状态 成功/失败/终止
|
|
58
|
-
*
|
|
52
|
+
* 成功 将直接返回 结果
|
|
53
|
+
* 终止 将直接返回 null
|
|
59
54
|
* 失败 将重试
|
|
60
55
|
*/
|
|
61
56
|
export type PromiseStat = "Completed" | "Failed" | "Terminated";
|
|
62
57
|
/**promise验证函数 */
|
|
63
58
|
export type PromiseVerifyFn<T> = (obj: T) => Promise<PromiseStat> | PromiseStat;
|
|
64
|
-
/**发起promise的函数 */
|
|
65
|
-
export type PromiseProcFn<T> = () => Promise<T>;
|
|
66
59
|
/**类型中任意函数的字符串名称 */
|
|
67
60
|
export type FuncPropNames<T> = {
|
|
68
|
-
[K in keyof T]: T[K] extends (...args:
|
|
61
|
+
[K in keyof T]: T[K] extends (...args: unknown[]) => unknown ? K : never;
|
|
69
62
|
}[keyof T];
|
|
70
63
|
/**部分组合的类
|
|
71
64
|
* @template Base - 基类
|
|
72
65
|
* @template Mixin - 待混入的类
|
|
73
66
|
* @template PropKeys - 需要混入的成员key
|
|
74
67
|
*/
|
|
75
|
-
export type ComposedClass<Base
|
|
68
|
+
export type ComposedClass<Base, Mixin, Key extends string, PropKeys extends keyof Mixin> = Base & Pick<Mixin, PropKeys> & {
|
|
76
69
|
[P in Key]: Mixin;
|
|
77
70
|
};
|
|
78
71
|
/**可自动混入的类型 */
|
|
@@ -87,5 +80,39 @@ export type Mixinable<Mixin> = {
|
|
|
87
80
|
readonly MIXIN_FIELDS: readonly (keyof Mixin)[];
|
|
88
81
|
};
|
|
89
82
|
/**自动组合可混入的类 */
|
|
90
|
-
export type ComposedMixinable<B
|
|
83
|
+
export type ComposedMixinable<B, Ms extends unknown[]> = Ms extends [infer M, ...infer Rest] ? M extends Mixinable<M> ? ComposedMixinable<ComposedClass<B, M, M['MIXIN_KEY'], M['MIXIN_FIELDS'][number]>, Rest> : "一个混入类没有实现 Mixinable<self>" & Error : B;
|
|
84
|
+
/** extends封装
|
|
85
|
+
* @template B - 基础类型
|
|
86
|
+
* @template T - 判断的目标类型
|
|
87
|
+
* @template Y - 如果为真的返回值
|
|
88
|
+
* @template N - 如果为假的返回值
|
|
89
|
+
*/
|
|
90
|
+
export type ExtendThen<B, T, Y, N = never> = B extends T ? Y : N;
|
|
91
|
+
/** 一个联合类型 B 中如果包含 T
|
|
92
|
+
* @template B - 基础类型
|
|
93
|
+
* @template T - 判断的目标类型
|
|
94
|
+
* @template Y - 如果为真的返回值
|
|
95
|
+
* @template N - 如果为假的返回值
|
|
96
|
+
*/
|
|
97
|
+
export type UnionInclude<B, T, Y, N = never> = B extends Exclude<B, T> ? Y : N;
|
|
98
|
+
/**排除可选字段 */
|
|
99
|
+
export type RequiredOnly<T> = {
|
|
100
|
+
[K in keyof T as UnionInclude<T[K], undefined, never, K>]: T[K];
|
|
101
|
+
};
|
|
102
|
+
/**添加前缀 */
|
|
103
|
+
export type WithPrefix<T, P extends string> = {
|
|
104
|
+
[K in (keyof T) as K extends string ? `${P}_${K}` : K]: T[K];
|
|
105
|
+
};
|
|
106
|
+
/**返回结果
|
|
107
|
+
* @template K - 类型键值
|
|
108
|
+
* @template V - 值
|
|
109
|
+
*/
|
|
110
|
+
export type Outcome<K extends string, V> = {
|
|
111
|
+
/**状态类型 */
|
|
112
|
+
status: K;
|
|
113
|
+
/**值 */
|
|
114
|
+
result: V;
|
|
115
|
+
};
|
|
116
|
+
/**从联合 Outcome 中 根据 id 提取对应 value 的 type */
|
|
117
|
+
export type ExtractOutcome<T, K extends string> = T extends Outcome<K, unknown> ? T : never;
|
|
91
118
|
export {};
|
package/dist/UtilInterfaces.js
CHANGED
|
@@ -1,14 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.stringifyJToken = void 0;
|
|
4
|
-
/**将JToken转换为字符串
|
|
5
|
-
* @param token - 待转换的Token
|
|
6
|
-
* @param space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
7
|
-
* @returns 转换完成的字符串
|
|
8
|
-
*/
|
|
9
|
-
function stringifyJToken(token, space = "\t") {
|
|
10
|
-
if (space == null)
|
|
11
|
-
space = undefined;
|
|
12
|
-
return JSON.stringify(token, null, space);
|
|
13
|
-
}
|
|
14
|
-
exports.stringifyJToken = stringifyJToken;
|
package/dist/test/composeTest.js
CHANGED
package/package.json
CHANGED
package/src/UtilCom.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JObject, PromiseVerifyFn
|
|
1
|
+
import { JObject, PromiseVerifyFn } from "@src/UtilInterfaces";
|
|
2
2
|
import * as https from 'https';
|
|
3
3
|
import * as http from 'http';
|
|
4
4
|
import { SLogger } from "@src/UtilLogger";
|
|
@@ -21,7 +21,7 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:num
|
|
|
21
21
|
if(hasTimeLimit)
|
|
22
22
|
timeLimit*=1000
|
|
23
23
|
|
|
24
|
-
const jsonStr = stringifyJToken(json);
|
|
24
|
+
const jsonStr = UtilFunc.stringifyJToken(json);
|
|
25
25
|
const funcName = `s${posttype}Psot`;
|
|
26
26
|
|
|
27
27
|
return new Promise((resolve, rejecte)=>{
|
|
@@ -55,7 +55,7 @@ function sPost(posttype:"http"|"https",json:JObject,options:Object,timeLimit:num
|
|
|
55
55
|
}
|
|
56
56
|
try{
|
|
57
57
|
let obj = JSON.parse(resdata);
|
|
58
|
-
SLogger.http(funcName+" 接受信息:",stringifyJToken(obj));
|
|
58
|
+
SLogger.http(funcName+" 接受信息:",UtilFunc.stringifyJToken(obj));
|
|
59
59
|
resolve(obj);
|
|
60
60
|
return;
|
|
61
61
|
}
|
package/src/UtilFP.ts
CHANGED
|
@@ -29,11 +29,13 @@ export function curry<T extends Function>(fn: T): CurryFunc<T> {
|
|
|
29
29
|
/**可组合的函数 */
|
|
30
30
|
type CompFunc<T, R> = (arg: T) => R;
|
|
31
31
|
|
|
32
|
+
|
|
32
33
|
/**函数管道组合
|
|
33
34
|
* 从左到右执行
|
|
34
35
|
* @param fs - 待组合的函数
|
|
35
36
|
* @returns 组合完成的函数
|
|
36
37
|
*/
|
|
38
|
+
//#region flow重载
|
|
37
39
|
export function flow<I>(...fs: CompFunc<I, I>[]): CompFunc<I, I>;
|
|
38
40
|
export function flow<I, R1>(f1: CompFunc<I, R1>,...fs: CompFunc<R1, R1>[]): CompFunc<I, R1>;
|
|
39
41
|
export function flow<I, R1, R2>(f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>,...fs: CompFunc<R2, R2>[]): CompFunc<I, R2>;
|
|
@@ -44,6 +46,7 @@ export function flow<I, R1, R2, R3, R4, R5, R6>(f1: CompFunc<I, R1>, f2: CompFun
|
|
|
44
46
|
export function flow<I, R1, R2, R3, R4, R5, R6, R7>(f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>,...fs: CompFunc<R7, R7>[]): CompFunc<I, R7>;
|
|
45
47
|
export function flow<I, R1, R2, R3, R4, R5, R6, R7, R8>(f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>, f8: CompFunc<R7, R8>,...fs: CompFunc<R8, R8>[]): CompFunc<I, R8>;
|
|
46
48
|
export function flow<I, R1, R2, R3, R4, R5, R6, R7, R8, R9>(f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>, f8: CompFunc<R7, R8>, f9: CompFunc<R8, R9>,...fs: CompFunc<R9, R9>[]): CompFunc<I, R9>;
|
|
49
|
+
//#endregion
|
|
47
50
|
export function flow<T>(...fs: ((arg: T) => T)[]): (arg: T) => T {
|
|
48
51
|
return (arg: T): T => {
|
|
49
52
|
return fs.reduce((value, func) => func(value), arg);
|
|
@@ -56,6 +59,7 @@ export function flow<T>(...fs: ((arg: T) => T)[]): (arg: T) => T {
|
|
|
56
59
|
* @param fs - 待组合的函数
|
|
57
60
|
* @returns 经过所有函数处理后的结果
|
|
58
61
|
*/
|
|
62
|
+
//#region pipe重载
|
|
59
63
|
export function pipe<I>(input: I, ...fs: CompFunc<I, I>[]): I;
|
|
60
64
|
export function pipe<I, R1>(input: I, f1: CompFunc<I, R1>,...fs: CompFunc<R1, R1>[]): R1;
|
|
61
65
|
export function pipe<I, R1, R2>(input: I, f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>,...fs: CompFunc<R2, R2>[]): R2;
|
|
@@ -66,6 +70,7 @@ export function pipe<I, R1, R2, R3, R4, R5, R6>(input: I, f1: CompFunc<I, R1>, f
|
|
|
66
70
|
export function pipe<I, R1, R2, R3, R4, R5, R6, R7>(input: I, f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>,...fs: CompFunc<R7, R7>[]): R7;
|
|
67
71
|
export function pipe<I, R1, R2, R3, R4, R5, R6, R7, R8>(input: I, f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>, f8: CompFunc<R7, R8>,...fs: CompFunc<R8, R8>[]): R8;
|
|
68
72
|
export function pipe<I, R1, R2, R3, R4, R5, R6, R7, R8, R9>(input: I, f1: CompFunc<I, R1>, f2: CompFunc<R1, R2>, f3: CompFunc<R2, R3>, f4: CompFunc<R3, R4>, f5: CompFunc<R4, R5>, f6: CompFunc<R5, R6>, f7: CompFunc<R6, R7>, f8: CompFunc<R7, R8>, f9: CompFunc<R8, R9>,...fs: CompFunc<R9, R9>[]): R9;
|
|
73
|
+
//#endregion
|
|
69
74
|
export function pipe<T>(input: T, ...fs: ((arg: T) => T)[]): T {
|
|
70
75
|
return fs.reduce((value, func) => func(value), input);
|
|
71
76
|
}
|
package/src/UtilFileTools.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
|
-
import { JToken
|
|
3
|
+
import { JToken } from "@src/UtilInterfaces";
|
|
4
4
|
import { SLogger } from "@src/UtilLogger";
|
|
5
5
|
import * as JSON5 from 'json5';
|
|
6
6
|
import { globSync } from "glob";
|
|
7
|
+
import { UtilFunc } from "./UtilFunctions";
|
|
7
8
|
|
|
8
9
|
/**文件工具 */
|
|
9
10
|
export namespace UtilFT{
|
|
@@ -178,7 +179,7 @@ export async function writeJSONFile(
|
|
|
178
179
|
filePath: string,
|
|
179
180
|
token: JToken
|
|
180
181
|
): Promise<void> {
|
|
181
|
-
let str = stringifyJToken(token);
|
|
182
|
+
let str = UtilFunc.stringifyJToken(token);
|
|
182
183
|
if (path.extname(filePath) !== '.json') filePath += '.json';
|
|
183
184
|
|
|
184
185
|
// 判断文件路径是否存在 不存在则创建
|
package/src/UtilFunctions.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as crypto from "crypto";
|
|
2
|
-
import { ComposedClass, ComposedMixinable, FuncPropNames, JToken, Mixinable,
|
|
2
|
+
import { ComposedClass, ComposedMixinable, ExtractOutcome, FuncPropNames, IJData, JObject, JToken, Mixinable, Outcome, PromiseStat, PromiseVerifyFn } from "@src/UtilInterfaces";
|
|
3
3
|
import * as cp from "child_process";
|
|
4
4
|
import { SLogger } from "@src/UtilLogger";
|
|
5
5
|
|
|
@@ -28,6 +28,27 @@ export function initField<T extends object,K extends keyof T>(
|
|
|
28
28
|
return obj[field];
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/**初始化一个数据对象
|
|
32
|
+
* @param obj - 目标对象
|
|
33
|
+
* @param checkObj - 用于检测的对象 在对应key缺失时赋予对应值 如果值为函数, 则赋予执行结果 如果结果为 undefined 则不赋值
|
|
34
|
+
* @returns 完成初始化的对象
|
|
35
|
+
*/
|
|
36
|
+
export function initObject<T extends JObject>
|
|
37
|
+
(obj:T,checkObj:{[P in keyof T]:T[P]|(()=>void|T[P])}){
|
|
38
|
+
const fixobj = obj as any;
|
|
39
|
+
for(const key in checkObj){
|
|
40
|
+
if(obj[key]!==undefined) continue;
|
|
41
|
+
|
|
42
|
+
const checkVal = checkObj[key];
|
|
43
|
+
if(typeof checkVal === "function"){
|
|
44
|
+
const val = checkVal();
|
|
45
|
+
if(val!==undefined) fixobj[key] = val;
|
|
46
|
+
}
|
|
47
|
+
else fixobj[key] = checkVal;
|
|
48
|
+
}
|
|
49
|
+
return fixobj
|
|
50
|
+
}
|
|
51
|
+
|
|
31
52
|
/**生成一串uuid
|
|
32
53
|
* @returns uuid
|
|
33
54
|
*/
|
|
@@ -112,36 +133,35 @@ type ProcessingPromise<T> = {
|
|
|
112
133
|
* @param verifyFn - 验证函数
|
|
113
134
|
* @param repeatCount - 重试次数
|
|
114
135
|
* @param repeatTime - 超时时间/秒 最小为10秒
|
|
115
|
-
* @returns
|
|
136
|
+
* @returns 结果 null 为全部失败/超时
|
|
116
137
|
*/
|
|
117
|
-
export async function repeatPromise<T>(procFn:
|
|
138
|
+
export async function repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:PromiseVerifyFn<T>,
|
|
118
139
|
repeatCount:number=3,repeatTime:number=180):Promise<T|null>{
|
|
119
140
|
|
|
120
141
|
//计时
|
|
121
142
|
const timeflag = "repeatPromise "+UtilFunc.genUUID();
|
|
122
143
|
SLogger.time(timeflag);
|
|
123
144
|
|
|
124
|
-
|
|
145
|
+
/**是否含有超时时间 */
|
|
125
146
|
const hasRepeatTime = (repeatTime>=10);
|
|
147
|
+
//转换为毫秒
|
|
126
148
|
if(hasRepeatTime) repeatTime*=1000;
|
|
127
149
|
|
|
128
150
|
//验证处理函数
|
|
129
151
|
if(verifyFn===undefined)
|
|
130
152
|
verifyFn = ()=>"Completed";
|
|
131
153
|
|
|
132
|
-
|
|
154
|
+
/**计时器 */
|
|
133
155
|
let timer:NodeJS.Timer|null = null;
|
|
156
|
+
/**计时器 Promise */
|
|
134
157
|
let timerP:Promise<"Timeout">|null=null;
|
|
135
|
-
|
|
158
|
+
/**计时器 Promise 的返回函数 */
|
|
159
|
+
let resolveFn:((value: "Timeout")=>void)|null = null;
|
|
136
160
|
/**清理计时器 */
|
|
137
161
|
const clearTimer = ()=>{
|
|
138
|
-
if(timer
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
resolveFn("Timeout");
|
|
142
|
-
timerP=null;
|
|
143
|
-
timer=null;
|
|
144
|
-
resolveFn=null;
|
|
162
|
+
if(timer) clearInterval(timer);
|
|
163
|
+
if(resolveFn) resolveFn("Timeout");
|
|
164
|
+
timerP = timer = resolveFn = null;
|
|
145
165
|
}
|
|
146
166
|
|
|
147
167
|
//进行中的请求
|
|
@@ -149,9 +169,11 @@ export async function repeatPromise<T>(procFn:PromiseProcFn<T>,verifyFn?:Promise
|
|
|
149
169
|
|
|
150
170
|
//开始处理
|
|
151
171
|
try{
|
|
172
|
+
//根据最大重试次数限制进行循环
|
|
152
173
|
for(let i=0;i<repeatCount;){
|
|
153
174
|
SLogger.info(`开始第 ${i+1} 次 repeatPromise`);
|
|
154
|
-
|
|
175
|
+
|
|
176
|
+
//如果 plist 中当前下标的任务还未创建 则 创建当前任务
|
|
155
177
|
if(plist.length<i+1){
|
|
156
178
|
plist.push(procFn().then(result =>
|
|
157
179
|
({result, stat:verifyFn!(result), index:i})));
|
|
@@ -159,46 +181,51 @@ export async function repeatPromise<T>(procFn:PromiseProcFn<T>,verifyFn?:Promise
|
|
|
159
181
|
|
|
160
182
|
//创建定时器
|
|
161
183
|
if(timerP==null){
|
|
162
|
-
timerP = new Promise<"Timeout">(
|
|
184
|
+
timerP = new Promise<"Timeout">((resolve, rejecte)=>{
|
|
163
185
|
resolveFn = resolve;
|
|
164
186
|
timer = setTimeout(()=>resolve("Timeout"),
|
|
165
|
-
hasRepeatTime? repeatTime:Infinity);//无限制则无限时间
|
|
187
|
+
hasRepeatTime ? repeatTime : Infinity);//无限制则无限时间
|
|
166
188
|
})
|
|
167
189
|
}
|
|
168
190
|
|
|
169
|
-
|
|
191
|
+
//等待任意任务 或当前计时器完成
|
|
170
192
|
const currObj = await Promise.race([...plist, timerP]);
|
|
171
193
|
|
|
172
194
|
//超时处理
|
|
173
|
-
if(currObj
|
|
195
|
+
if(currObj==="Timeout"){
|
|
174
196
|
SLogger.warn(`第 ${i+1} 次 repeatPromise 超时 ${repeatTime} ms 开始重试`);
|
|
175
197
|
clearTimer(); i++;
|
|
176
198
|
continue;
|
|
177
199
|
}
|
|
200
|
+
|
|
201
|
+
//路由请求状态
|
|
178
202
|
const poststat = await currObj.stat;
|
|
179
|
-
|
|
180
|
-
|
|
203
|
+
const result = matchStr(poststat,{
|
|
204
|
+
Completed(){
|
|
181
205
|
SLogger.info(`第 ${currObj.index+1} 次 repeatPromise 成功`);
|
|
182
206
|
//非当前
|
|
183
207
|
if(currObj.index!=i)
|
|
184
208
|
SLogger.info(`成功的 promise 非当前 promise 考虑增大重试间隔\n当前index: ${i}\n当前间隔: ${repeatTime}`);
|
|
185
209
|
return currObj.result;
|
|
186
|
-
|
|
210
|
+
},
|
|
211
|
+
Terminated(){
|
|
187
212
|
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 终止 停止重试`);
|
|
188
213
|
return currObj.result;
|
|
189
|
-
|
|
214
|
+
},
|
|
215
|
+
Failed(){
|
|
190
216
|
//抛弃失败
|
|
191
217
|
plist[currObj.index] = UtilFunc.getNeverResolvedPromise();
|
|
192
218
|
//是当前
|
|
193
219
|
if(currObj.index==i){
|
|
194
220
|
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 失败 开始重试`);
|
|
195
221
|
clearTimer(); i++;
|
|
196
|
-
|
|
222
|
+
return;
|
|
197
223
|
}
|
|
198
224
|
//非当前
|
|
199
225
|
SLogger.warn(`第 ${currObj.index+1} 次 repeatPromise 失败`);
|
|
200
|
-
|
|
201
|
-
}
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
if(result !== undefined) return result;
|
|
202
229
|
}
|
|
203
230
|
//全部失败或超时则返回null
|
|
204
231
|
SLogger.warn(`${repeatCount} 次 repeatPromise 尝试均失败`);
|
|
@@ -291,4 +318,36 @@ export function mapEntries<T extends Object>
|
|
|
291
318
|
}, {} as T);
|
|
292
319
|
}
|
|
293
320
|
|
|
321
|
+
/**处理联合 Outcome
|
|
322
|
+
* @param t - 目标值
|
|
323
|
+
* @param procObj - 所有可能的id组成的处理函数映射
|
|
324
|
+
* @returns 任意处理函数的返回值
|
|
325
|
+
*/
|
|
326
|
+
export function matchOutcome<
|
|
327
|
+
T extends Outcome<string,unknown>,
|
|
328
|
+
P extends {[K in T['status']]:(k:K,v:ExtractOutcome<T,K>['result'])=>unknown}>
|
|
329
|
+
(t:T,procObj:P):{[K in keyof P]:ReturnType<P[K]>}[keyof P]{
|
|
330
|
+
return (procObj as any)[t.status](t.status,(t as any)?.result)
|
|
331
|
+
}
|
|
332
|
+
/**处理联合 字符串
|
|
333
|
+
* @param t - 目标值
|
|
334
|
+
* @param procObj - 所有可能的id组成的处理函数映射
|
|
335
|
+
* @returns 任意处理函数的返回值
|
|
336
|
+
*/
|
|
337
|
+
export function matchStr<T extends string,P extends {[K in T]:(k:K)=>unknown}>
|
|
338
|
+
(t:T,procObj:P):{[K in keyof P]:ReturnType<P[K]>}[keyof P]{
|
|
339
|
+
return (procObj as any)[t](t)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**将JToken转换为字符串
|
|
343
|
+
* @param token - 待转换的Token
|
|
344
|
+
* @param space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
345
|
+
* @returns 转换完成的字符串
|
|
346
|
+
*/
|
|
347
|
+
export function stringifyJToken(token:JToken|IJData,space:string|number|null|undefined="\t"){
|
|
348
|
+
if(space==null)
|
|
349
|
+
space=undefined;
|
|
350
|
+
return JSON.stringify(token,null,space);
|
|
351
|
+
}
|
|
352
|
+
|
|
294
353
|
}
|
package/src/UtilInterfaces.ts
CHANGED
|
@@ -16,16 +16,6 @@ export interface IJData{
|
|
|
16
16
|
*/
|
|
17
17
|
toJSON():JToken;
|
|
18
18
|
}
|
|
19
|
-
/**将JToken转换为字符串
|
|
20
|
-
* @param token - 待转换的Token
|
|
21
|
-
* @param space - 插入的空格 数字为空格数量 默认为制表符\t
|
|
22
|
-
* @returns 转换完成的字符串
|
|
23
|
-
*/
|
|
24
|
-
export function stringifyJToken(token:JToken|IJData,space:string|number|null|undefined="\t"){
|
|
25
|
-
if(space==null)
|
|
26
|
-
space=undefined;
|
|
27
|
-
return JSON.stringify(token,null,space);
|
|
28
|
-
}
|
|
29
19
|
|
|
30
20
|
/**转为可写的 */
|
|
31
21
|
export type Writeable<T> = {
|
|
@@ -73,18 +63,17 @@ export type ExclusiveJObject<B extends JObject,T extends JToken,K extends string
|
|
|
73
63
|
|
|
74
64
|
|
|
75
65
|
/**请求完成状态 成功/失败/终止
|
|
76
|
-
*
|
|
66
|
+
* 成功 将直接返回 结果
|
|
67
|
+
* 终止 将直接返回 null
|
|
77
68
|
* 失败 将重试
|
|
78
69
|
*/
|
|
79
70
|
export type PromiseStat = "Completed"|"Failed"|"Terminated";
|
|
80
71
|
/**promise验证函数 */
|
|
81
72
|
export type PromiseVerifyFn<T> = (obj:T)=>Promise<PromiseStat>|PromiseStat;
|
|
82
|
-
/**发起promise的函数 */
|
|
83
|
-
export type PromiseProcFn<T> = ()=>Promise<T>;
|
|
84
73
|
|
|
85
74
|
/**类型中任意函数的字符串名称 */
|
|
86
75
|
export type FuncPropNames<T> = {
|
|
87
|
-
[K in keyof T]: T[K] extends (...args:
|
|
76
|
+
[K in keyof T]: T[K] extends (...args: unknown[]) => unknown ? K : never;
|
|
88
77
|
}[keyof T];
|
|
89
78
|
|
|
90
79
|
/**部分组合的类
|
|
@@ -92,7 +81,7 @@ export type FuncPropNames<T> = {
|
|
|
92
81
|
* @template Mixin - 待混入的类
|
|
93
82
|
* @template PropKeys - 需要混入的成员key
|
|
94
83
|
*/
|
|
95
|
-
export type ComposedClass<Base
|
|
84
|
+
export type ComposedClass<Base, Mixin, Key extends string, PropKeys extends keyof Mixin> =
|
|
96
85
|
Base & Pick<Mixin, PropKeys> & {[P in Key]:Mixin};
|
|
97
86
|
|
|
98
87
|
/**可自动混入的类型 */
|
|
@@ -108,9 +97,56 @@ export type Mixinable<Mixin> = {
|
|
|
108
97
|
};
|
|
109
98
|
|
|
110
99
|
/**自动组合可混入的类 */
|
|
111
|
-
export type ComposedMixinable<B
|
|
100
|
+
export type ComposedMixinable<B, Ms extends unknown[]> =
|
|
112
101
|
Ms extends [infer M, ...infer Rest]
|
|
113
102
|
? M extends Mixinable<M>
|
|
114
103
|
? ComposedMixinable<ComposedClass<B,M,M['MIXIN_KEY'],M['MIXIN_FIELDS'][number]>,Rest>
|
|
115
104
|
: "一个混入类没有实现 Mixinable<self>" & Error
|
|
116
105
|
: B
|
|
106
|
+
|
|
107
|
+
/** extends封装
|
|
108
|
+
* @template B - 基础类型
|
|
109
|
+
* @template T - 判断的目标类型
|
|
110
|
+
* @template Y - 如果为真的返回值
|
|
111
|
+
* @template N - 如果为假的返回值
|
|
112
|
+
*/
|
|
113
|
+
export type ExtendThen<B,T,Y,N = never> = B extends T ? Y : N;
|
|
114
|
+
/** 一个联合类型 B 中如果包含 T
|
|
115
|
+
* @template B - 基础类型
|
|
116
|
+
* @template T - 判断的目标类型
|
|
117
|
+
* @template Y - 如果为真的返回值
|
|
118
|
+
* @template N - 如果为假的返回值
|
|
119
|
+
*/
|
|
120
|
+
export type UnionInclude<B,T,Y,N = never> =
|
|
121
|
+
B extends Exclude<B,T>
|
|
122
|
+
? Y
|
|
123
|
+
: N
|
|
124
|
+
/**排除可选字段 */
|
|
125
|
+
export type RequiredOnly<T> = {
|
|
126
|
+
[K in keyof T as
|
|
127
|
+
UnionInclude<T[K],undefined,never,K>
|
|
128
|
+
]: T[K]
|
|
129
|
+
};
|
|
130
|
+
/**添加前缀 */
|
|
131
|
+
export type WithPrefix<T,P extends string> = {
|
|
132
|
+
[K in (keyof T) as
|
|
133
|
+
K extends string
|
|
134
|
+
? `${P}_${K}`
|
|
135
|
+
: K
|
|
136
|
+
]: T[K]
|
|
137
|
+
};
|
|
138
|
+
/**返回结果
|
|
139
|
+
* @template K - 类型键值
|
|
140
|
+
* @template V - 值
|
|
141
|
+
*/
|
|
142
|
+
export type Outcome<K extends string,V> = {
|
|
143
|
+
/**状态类型 */
|
|
144
|
+
status:K;
|
|
145
|
+
/**值 */
|
|
146
|
+
result:V;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**从联合 Outcome 中 根据 id 提取对应 value 的 type */
|
|
150
|
+
export type ExtractOutcome<T,K extends string> =
|
|
151
|
+
T extends Outcome<K,unknown> ? T : never;
|
|
152
|
+
|
package/src/test/composeTest.ts
CHANGED
|
@@ -91,3 +91,44 @@ insd.getNum()//?
|
|
|
91
91
|
insd.__a = new A(3);
|
|
92
92
|
insd.getNum()//?
|
|
93
93
|
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
type jo = {
|
|
97
|
+
a?:number,
|
|
98
|
+
b?:string,
|
|
99
|
+
c:number,
|
|
100
|
+
}
|
|
101
|
+
let jot = {
|
|
102
|
+
c:1
|
|
103
|
+
} as jo;
|
|
104
|
+
UtilFunc.initObject(jot,{
|
|
105
|
+
c:()=>console.log("缺少c"+insd.getNum())
|
|
106
|
+
})
|
|
107
|
+
jot//?
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
type IfUndefined<T, Y, N> = T extends undefined ? Y : N;
|
|
111
|
+
|
|
112
|
+
type RequiredOnly<T> = {
|
|
113
|
+
[K in (keyof T) as
|
|
114
|
+
T[K] extends Exclude<T[K],undefined>
|
|
115
|
+
? K
|
|
116
|
+
: never
|
|
117
|
+
]: T[K]
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
type WithPrefix<T,P extends string> = {
|
|
122
|
+
[K in (keyof T) as
|
|
123
|
+
K extends string
|
|
124
|
+
? `${P}_${K}`
|
|
125
|
+
: K
|
|
126
|
+
]: T[K]
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
type a= {
|
|
130
|
+
abc:123
|
|
131
|
+
def?:1
|
|
132
|
+
}
|
|
133
|
+
type d = RequiredOnly<a>;
|
|
134
|
+
type b = WithPrefix<a,"prefix">;
|