default-template
Version:
一个用于定义默认值和转换对象结构的实用工具
270 lines (269 loc) • 14.9 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
/// <reference types="vitest" />
const vitest_1 = require("vitest");
const index_1 = __importStar(require("./index"));
(0, vitest_1.describe)('defaultTemplate', () => {
(0, vitest_1.it)('基本类型:undefined/null 返回默认值', () => {
const result1 = (0, index_1.default)(10, undefined);
console.log('基本类型:undefined/null 返回默认值', result1);
(0, vitest_1.expect)(result1).toBe(10);
const result2 = (0, index_1.default)(10, null);
console.log('基本类型:undefined/null 返回默认值', result2);
(0, vitest_1.expect)(result2).toBe(10);
const result3 = (0, index_1.default)(false, undefined);
console.log('基本类型:undefined/null 返回默认值', result3);
(0, vitest_1.expect)(result3).toBe(false);
const result4 = (0, index_1.default)('', undefined);
console.log('基本类型:undefined/null 返回默认值', result4);
(0, vitest_1.expect)(result4).toBe('');
});
(0, vitest_1.it)('基本类型:类型自动转换', () => {
const result1 = (0, index_1.default)(10, '20');
console.log('基本类型:类型自动转换', result1);
(0, vitest_1.expect)(result1).toBe(20);
const result2 = (0, index_1.default)(false, 'true');
console.log('基本类型:类型自动转换', result2);
(0, vitest_1.expect)(result2).toBe(true);
const result3 = (0, index_1.default)(false, 'false');
console.log('基本类型:类型自动转换', result3);
(0, vitest_1.expect)(result3).toBe(false);
const result4 = (0, index_1.default)('', 123);
console.log('基本类型:类型自动转换', result4);
(0, vitest_1.expect)(result4).toBe('123');
const result5 = (0, index_1.default)(BigInt(1), '2');
console.log('基本类型:类型自动转换', result5);
(0, vitest_1.expect)(result5).toBe('2'); // bigint 作为模板时,字符串原样返回
const result6 = (0, index_1.default)(Symbol('a'), Symbol('b'));
console.log('基本类型:类型自动转换', typeof result6);
(0, vitest_1.expect)(typeof result6).toBe('symbol');
});
(0, vitest_1.it)('基本类型:function 作为模板', () => {
const fn = (x) => (typeof x === 'number' ? x * 2 : 0);
let result = (0, index_1.default)(fn, 5);
console.log('基本类型:function 作为模板', result);
(0, vitest_1.expect)(result).toBe(10);
result = (0, index_1.default)(fn, undefined);
console.log('基本类型:function 作为模板', result);
(0, vitest_1.expect)(result).toBe(0);
});
(0, vitest_1.it)('基本类型:Date 作为模板', () => {
const d = new Date('2020-01-01');
const d2 = new Date('2022-01-01');
let result = (0, index_1.default)(d, d2);
console.log('基本类型:Date 作为模板', result);
(0, vitest_1.expect)(result).toBe(d2);
result = (0, index_1.default)(d, undefined);
console.log('基本类型:Date 作为模板', result);
(0, vitest_1.expect)(result).toBe(d);
});
(0, vitest_1.it)('基本类型:原样返回', () => {
let result = (0, index_1.default)(null, 10);
console.log('基本类型:原样返回', result);
(0, vitest_1.expect)(result).toBe(10);
result = (0, index_1.default)(null, '10');
console.log('基本类型:原样返回', result);
(0, vitest_1.expect)(result).toBe('10');
result = (0, index_1.default)(null, { a: 1 });
console.log('基本类型:原样返回', result);
(0, vitest_1.expect)(result).toEqual({ a: 1 });
});
(0, vitest_1.it)('数组:元素模板', () => {
const result1 = (0, index_1.default)([10], [null, '20', 20]);
console.log('数组:元素模板', result1);
(0, vitest_1.expect)(result1).toEqual([10, 20, 20]);
const result2 = (0, index_1.default)([false], [1, 0, 'false']);
console.log('数组:元素模板', result2);
(0, vitest_1.expect)(result2).toEqual([true, false, false]);
const result3 = (0, index_1.default)([{ a: 1 }], [{ a: 2, b: 3 }, { a: '3', b: 4 }]);
console.log('数组:元素模板', result3);
// 只保留模板字段 a
(0, vitest_1.expect)(result3).toEqual([{ a: 2 }, { a: 3 }]);
});
(0, vitest_1.it)('数组:嵌套数组', () => {
const result = (0, index_1.default)([[0]], [[1, 2], [3, null]]);
console.log('数组:嵌套数组', result);
(0, vitest_1.expect)(result).toEqual([[1, 2], [3, 0]]);
});
(0, vitest_1.it)('数组:空模板数组', () => {
let result = (0, index_1.default)([], [1, 2, 3]);
console.log('数组:空模板数组', result);
(0, vitest_1.expect)(result).toEqual([1, 2, 3]);
result = (0, index_1.default)([], undefined);
console.log('数组:空模板数组', result);
(0, vitest_1.expect)(result).toEqual([]);
});
(0, vitest_1.it)('对象:基础对象模板', () => {
const result = (0, index_1.default)({ a: 10, b: false, c: 20 }, { a: '20', b: null, d: 'test' });
console.log('对象:基础对象模板', result);
(0, vitest_1.expect)(result).toEqual({ a: 20, b: false, c: 20 });
});
(0, vitest_1.it)('对象:深层嵌套对象', () => {
const def = { a: { b: { c: 1 } } };
const src = { a: { b: { c: '2', d: 3 }, e: 4 } };
const result = (0, index_1.default)(def, src);
console.log('对象:深层嵌套对象', result);
(0, vitest_1.expect)(result).toEqual({ a: { b: { c: 2 } } });
});
(0, vitest_1.it)('对象:通配符模板', () => {
const result1 = (0, index_1.default)({ '?': true }, { x: null, y: false });
console.log('对象:通配符模板', result1);
(0, vitest_1.expect)(result1).toEqual({ x: true, y: false });
const result2 = (0, index_1.default)({ a: 1, '?': 0 }, { a: 2, b: '3', c: null });
console.log('对象:通配符模板', result2);
(0, vitest_1.expect)(result2).toEqual({ a: 2, b: 3, c: 0 });
});
(0, vitest_1.it)('对象:通配符与显式key混用', () => {
const result = (0, index_1.default)({ a: 1, '?': 2 }, { a: undefined, b: 3 });
console.log('对象:通配符与显式key混用', result);
(0, vitest_1.expect)(result).toEqual({ a: 1, b: 3 });
});
(0, vitest_1.it)('对象:自定义通配符键名', () => {
const result = (0, index_1.default)({ '*': 1 }, { a: null, b: 2 }, { allTemplateKey: '*' });
console.log('对象:自定义通配符键名', result);
(0, vitest_1.expect)(result).toEqual({ a: 1, b: 2 });
});
(0, vitest_1.it)('对象:空对象模板', () => {
let result = (0, index_1.default)({}, { a: 1 });
console.log('对象:空对象模板', result);
(0, vitest_1.expect)(result).toEqual({});
result = (0, index_1.default)({}, {});
console.log('对象:空对象模板', result);
(0, vitest_1.expect)(result).toEqual({});
});
(0, vitest_1.it)('对象:嵌套结构', () => {
const def = { user: { name: '', age: 0, tags: [''] }, active: false };
const src = { user: { name: '张三', age: '18', tags: [null, 'vip'] }, active: 'true', extra: 123 };
const result = (0, index_1.default)(def, src);
console.log('对象:嵌套结构', result);
(0, vitest_1.expect)(result).toEqual({ user: { name: '张三', age: 18, tags: ['', 'vip'] }, active: true });
});
(0, vitest_1.it)('对象:键名映射', () => {
const def = { id: 0, name: new index_1.TemplateRename('username', '') };
const src = { id: 1, name: '张三' };
const result = (0, index_1.default)(def, src);
console.log('对象:键名映射', result);
(0, vitest_1.expect)(result).toEqual({ id: 1, username: '张三' });
});
(0, vitest_1.it)('对象:键名映射为函数', () => {
const def = { foo: new index_1.TemplateRename(k => 'bar_' + k, 1) };
const src = { foo: 2 };
const result = (0, index_1.default)(def, src);
console.log('对象:键名映射为函数', result);
(0, vitest_1.expect)(result).toEqual({ bar_foo: 2 });
});
(0, vitest_1.it)('对象:TemplateRename 嵌套', () => {
const def = { a: new index_1.TemplateRename('b', new index_1.TemplateRename('c', 1)) };
const src = { a: 2 };
const result = (0, index_1.default)(def, src);
console.log('对象:TemplateRename 嵌套', result);
(0, vitest_1.expect)(result).toEqual({ c: 2 });
});
(0, vitest_1.it)('自定义处理函数', () => {
const result1 = (0, index_1.default)((data) => Array.isArray(data) ? data.length : 0, [1, 2, 3]);
console.log('自定义处理函数', result1);
(0, vitest_1.expect)(result1).toBe(3);
const result2 = (0, index_1.default)((data) => typeof data === 'string' ? data.toUpperCase() : '', 'abc');
console.log('自定义处理函数', result2);
(0, vitest_1.expect)(result2).toBe('ABC');
// 测试 owner 参数
const result3 = (0, index_1.default)((data, owner) => owner && owner.flag ? 1 : 0, 5, undefined);
console.log('自定义处理函数', result3);
(0, vitest_1.expect)(result3).toBe(0);
const result4 = (0, index_1.default)((data, owner) => owner && owner.flag ? 1 : 0, 5, undefined);
console.log('自定义处理函数', result4);
(0, vitest_1.expect)(result4).toBe(0);
const result5 = (0, index_1.default)((data, owner) => owner && owner.flag ? 1 : 0, 5, undefined);
console.log('自定义处理函数', result5);
(0, vitest_1.expect)(result5).toBe(0);
});
(0, vitest_1.it)('边界:模板为 null/undefined', () => {
const result1 = (0, index_1.default)(null, 123);
console.log('边界:模板为 null/undefined', result1);
(0, vitest_1.expect)(result1).toBe(123);
const result2 = (0, index_1.default)(undefined, 456);
console.log('边界:模板为 null/undefined', result2);
(0, vitest_1.expect)(result2).toBe(456);
});
(0, vitest_1.it)('边界:src 为 null/undefined', () => {
const result1 = (0, index_1.default)(1, null);
console.log('边界:src 为 null/undefined', result1);
(0, vitest_1.expect)(result1).toBe(1);
const result2 = (0, index_1.default)({ a: 1 }, null);
console.log('边界:src 为 null/undefined', result2);
(0, vitest_1.expect)(result2).toEqual({ a: 1 });
const result3 = (0, index_1.default)([1], null);
console.log('边界:src 为 null/undefined', result3);
(0, vitest_1.expect)(result3).toEqual([]);
});
(0, vitest_1.it)('边界:对象模板未声明的字段被删除', () => {
const result = (0, index_1.default)({ a: 1 }, { a: 2, b: 3 });
console.log('边界:对象模板未声明的字段被删除', result);
(0, vitest_1.expect)(result).toEqual({ a: 2 });
});
(0, vitest_1.it)('边界:数组模板长度为0', () => {
let result = (0, index_1.default)([], [1, 2, 3]);
console.log('边界:数组模板长度为0', result);
(0, vitest_1.expect)(result).toEqual([1, 2, 3]);
result = (0, index_1.default)([], undefined);
console.log('边界:数组模板长度为0', result);
(0, vitest_1.expect)(result).toEqual([]);
});
(0, vitest_1.it)('极端情况:模板和数据都为 undefined/null/空', () => {
const result1 = (0, index_1.default)(undefined, undefined);
console.log('极端情况:模板和数据都为 undefined/null/空', result1);
(0, vitest_1.expect)(result1).toBe(undefined);
const result2 = (0, index_1.default)(null, null);
console.log('极端情况:模板和数据都为 undefined/null/空', result2);
(0, vitest_1.expect)(result2).toBe(null);
const result3 = (0, index_1.default)({}, undefined);
console.log('极端情况:模板和数据都为 undefined/null/空', result3);
(0, vitest_1.expect)(result3).toEqual({});
const result4 = (0, index_1.default)([], undefined);
console.log('极端情况:模板和数据都为 undefined/null/空', result4);
(0, vitest_1.expect)(result4).toEqual([]);
});
(0, vitest_1.it)('异常输入:模板为非对象/数组/基本类型/函数', () => {
const result1 = (0, index_1.default)(new Set([1]), [1]);
console.log('异常输入:模板为非对象/数组/基本类型/函数', result1);
(0, vitest_1.expect)(result1).toEqual(new Set([1]));
const result2 = (0, index_1.default)(new Map([[1, 2]]), { a: 1 });
console.log('异常输入:模板为非对象/数组/基本类型/函数', result2);
(0, vitest_1.expect)(result2).toEqual(new Map([[1, 2]]));
});
(0, vitest_1.it)('泛型推断:类型安全', () => {
const def = { id: 0, name: '', active: false };
const user = (0, index_1.default)(def, { id: '1', name: '张三', active: 'true' });
console.log('泛型推断:类型安全', user);
(0, vitest_1.expect)(user).toEqual({ id: 1, name: '张三', active: true });
});
(0, vitest_1.it)('数组模板:字段补全', () => {
const result = (0, index_1.default)([{ min: 0 }], [{ val: -1 }, { val: 5 }]);
console.log('数组模板:字段补全', result);
// 只保留模板字段 min
(0, vitest_1.expect)(result).toEqual([{ min: 0 }, { min: 0 }]);
});
});