Relationship TypeScript
February 10, 2026 · View on GitHub
中文亲戚关系计算器的 TypeScript 重构版本,针对性能和移动端兼容性进行了优化。
📖 文档: https://docs.qinyimo.cn/ | 🎮 在线演示: https://example.qinyimo.cn/
🎯 为什么需要 TypeScript 版本?
本项目基于 mumuy/relationship 进行 TypeScript 重构优化。
解决的问题
在 React Native 移动端 使用原版 JS 包时,会出现以下错误:
ERROR [RangeError: Property storage exceeds 196607 properties]
这是由于原版 JS 在初始化时创建了大量的对象属性,超出了 JavaScriptCore 引擎的属性数量限制。
TypeScript 版本通过以下优化解决了这个问题:
- ✅ 使用
Map代替Object存储数据 - ✅ 实现 LRU 缓存机制,按需加载
- ✅ 优化数据结构,减少内存占用
✨ 特性
| 特性 | JS 版本 | TS 版本 |
|---|---|---|
| 类型支持 | ❌ | ✅ 完整的 TypeScript 类型 |
| 包体积 | 83.3 KB | 78.9 KB (-5%) |
| 重复查询性能 | ~2ms | ~0.1ms (提升95%) |
| React Native | ⚠️ 可能报错 | ✅ 完美支持 |
| LRU 缓存 | ❌ | ✅ 智能缓存 |
| Tree Shaking | 部分支持 | ✅ 完整支持 |
🔧 主要优化
- LRU 缓存机制 - 缓存常用查询结果,重复查询性能提升 95%
- Map 数据结构 - 使用 Map 代替 Object,O(1) 查找性能
- 类型安全 - 完整的 TypeScript 类型定义
- 更小体积 - 优化后的包体积减少约 5%
📦 安装
# 使用 npm
npm install relationship-ts
# 使用 pnpm
pnpm add relationship-ts
# 使用 yarn
yarn add relationship-ts
多种导入方式
// 主库(简体中文)
import relationship from 'relationship-ts';
// 繁体中文版本(zh-HK)
import relationship from 'relationship-ts/zh-HK';
// 方言模式数据
import { guangdong, north } from 'relationship-ts/locale/guangdong';
import north from 'relationship-ts/locale/north';
浏览器使用
<!-- 主库 -->
<script src="path/to/relationship.min.js"></script>
<!-- 繁体中文版本 -->
<script src="path/to/lang/relationship.zh-HK.min.js"></script>
<!-- 方言模式 -->
<script src="path/to/relationship-mode.min.js"></script>
<script>
// 设置广东方言模式
relationship.setMode('guangdong', relationshipMode.guangdong.data);
</script>
🚀 使用方法
基本用法
import relationship from 'relationship-ts';
// 查询称谓
relationship({ text: '爸爸的妈妈' });
// => ['奶奶', '祖母']
// 查询多层关系
relationship({ text: '妈妈的妈妈的哥哥' });
// => ['舅外公']
反向查询
// 对方称呼我什么?
relationship({ text: '外婆', reverse: true, sex: 1 });
// => ['外孙']
relationship({ text: '外婆', reverse: true, sex: 0 });
// => ['外孙女']
关系链查询
// 查询某个称谓代表什么关系
relationship({ text: '舅公', type: 'chain' });
// => ['爸爸的妈妈的兄弟', '妈妈的妈妈的兄弟']
关系合称
// 查询两个人之间的关系合称
relationship({ text: '外婆', target: '奶奶', type: 'pair' });
// => ['儿女亲家']
relationship({ text: '哥哥', target: '弟弟', type: 'pair' });
// => ['兄弟']
相对关系
// 舅妈如何称呼外婆?
relationship({ text: '外婆', target: '舅妈', sex: 1 });
// => ['婆婆']
自然语言模式
// 支持自然语言表达式
relationship('舅妈如何称呼外婆?');
// => ['婆婆']
relationship('外婆和奶奶之间是什么关系?');
// => ['儿女亲家']
relationship('爸爸的妈妈是谁?');
// => ['奶奶', '祖母']
自定义方言模式
// 设置北方方言模式
relationship.setMode('northern', {
'm,f': ['姥爷'],
'm,m': ['姥姥'],
'm,xb,s&o': ['表哥'],
'm,xb,s&l': ['表弟'],
});
// 使用自定义模式
relationship({ text: '妈妈的妈妈', mode: 'northern' });
// => ['姥姥']
📖 API 参考
relationship(options)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text | string | '' | 目标对象的称谓,称谓间用"的"字分隔 |
target | string | '' | 相对对象的称谓,空表示自己 |
sex | -1 | 0 | 1 | -1 | 本人性别:-1未知,0女性,1男性 |
type | 'default' | 'chain' | 'pair' | 'default' | 转换类型 |
reverse | boolean | false | 称呼方式:true对方称呼我 |
mode | string | 'default' | 使用的方言模式 |
optimal | boolean | false | 计算最短关系 |
relationship.setMode(name, data)
设置自定义方言模式。
relationship.setMode('custom', {
'f': ['老爸', '爹地'],
'm': ['老妈', '妈咪'],
});
relationship.data
获取当前数据表。
relationship.dataCount
获取当前数据量。
🔤 关系链语法
| 符号 | 含义 | 符号 | 含义 |
|---|---|---|---|
f | 父亲 | m | 母亲 |
h | 丈夫 | w | 妻子 |
s | 儿子 | d | 女儿 |
xb | 兄弟 | xs | 姐妹 |
ob | 哥哥 | lb | 弟弟 |
os | 姐姐 | ls | 妹妹 |
修饰符
| 符号 | 含义 |
|---|---|
1 | 男性 |
0 | 女性 |
&o | 年长 |
&l | 年幼 |
&数字 | 排行 |
📁 项目结构
ts-version/
├── src/
│ ├── core/ # 核心模块
│ │ ├── cache.ts # 缓存系统(Map优化)
│ │ ├── id.ts # 关系链转中文
│ │ ├── lru.ts # LRU缓存实现
│ │ ├── mode.ts # 模式管理
│ │ └── selector.ts # 中文转关系链
│ ├── data/ # 数据文件
│ ├── rules/ # 规则文件
│ ├── utils/ # 工具函数
│ ├── locale/ # 方言数据
│ ├── types.ts # 类型定义
│ └── index.ts # 主入口
└── package.json
├── dist/ # 构建产物
│ ├── relationship.min.mjs # ESM格式
│ ├── relationship.min.js # UMD格式
│ ├── index.d.ts # 类型声明
│ ├── locale/ # 方言数据
│ │ ├── guangdong.min.mjs
│ │ └── north.min.mjs
│ └── lang/ # 繁体中文 (zh-HK)
│ └── relationship.zh-HK.min.mjs
├── rollup.config.mjs # Rollup配置
├── gulpfile.mjs # Gulp配置 (繁体转换)
├── tsconfig.json # TypeScript配置
└── package.json
🛠️ 开发
# 安装依赖
pnpm install
# 构建
pnpm run build
# 开发模式(监听文件变化)
pnpm run dev
# 类型检查
pnpm run type-check
🧪 测试
项目使用 Vitest 作为测试框架,包含 322 个测试用例,覆盖从纯函数单元测试到复杂亲属关系的端到端回归测试。
# 运行全部测试
pnpm test
# 监听模式(开发时自动重跑)
pnpm test:watch
# 运行测试并生成覆盖率报告
pnpm test:coverage
测试结构
tests/
├── setup.ts # 全局初始化
├── utils/
│ ├── unit.test.ts # zh2number / number2zh 纯函数
│ └── options.test.ts # 自然语言表达式解析
├── core/
│ ├── lru.test.ts # LRU 缓存淘汰策略
│ ├── cache.test.ts # OptimizedCache 称谓映射
│ ├── mode.test.ts # 方言模式切换与合并
│ ├── id.test.ts # 关系链逆转、世代计算、称谓查找、合称
│ └── selector.test.ts # 中文→关系链转换、选择器合并与展开
├── rules/
│ └── expression.test.ts # 自然语言表达式规则匹配
├── data/
│ └── integrity.test.ts # 数据格式完整性校验
├── integration/
│ └── relationship.test.ts # relationship() 主函数集成测试
└── regression/
└── queries.test.ts # 98 条亲属关系回归测试(含五辈以上、堂表亲、姻亲等)
📊 性能基准测试
基于 Node.js 环境的性能压力测试结果(复杂随机查询):
| 指标 | 结果 | 说明 |
|---|---|---|
| 冷启动 QPS | ~14,000 req/s | 无缓存/首次查询性能 |
| 热启动 QPS | ~30,000 req/s | 命中 LRU 缓存性能 |
| 平均耗时 | 0.033 ms | 命中缓存时的单次查询耗时 |
| 性能提升 | 2.1 倍 | 相比无缓存状态的吞吐量提升 |
测试环境:Node.js v20+, 单核性能
资源占用对比
| 项目 | 原版 (JS) | 优化版 (TS) | 提升 |
|---|---|---|---|
| 包体积 (Minified) | 83.3 KB | 78.9 KB | ⬇️ 5% |
| 重复查询耗时 | ~2 ms | ~0.03 ms | 🚀 60倍 |
| 内存溢出风险 | 高 (RN) | 无 | ✅ 解决 |
🙏 致谢
本项目基于 mumuy/relationship 进行 TypeScript 重构。
感谢原作者 mumuy 开发的优秀的中国家庭称谓计算器!
原项目地址:https://github.com/mumuy/relationship
演示地址:https://passer-by.com/relationship/
特别感谢 @xu133081 对本项目的测试支持!
📄 许可证
如果这个项目对你有帮助,请给原项目 ⭐️ Star!