语言工具链与准确数据表示
按宿主配置检查和构建,处理环境变量、测试、金额、日期及通用工具的语义。
配置跟随实际执行目标
浏览器打包项目、Node 直接运行项目和发布库的模块规则不同。共享 tsconfig 可集中严格检查,叶子项目按真实宿主指定模块、解析方式、可用类型和输出。声明 types 控制全局声明范围,lib 描述可用平台 API;二者不会安装实际能力。
strict、noUncheckedIndexedAccess 与 exactOptionalPropertyTypes 分别影响检查范围、索引可能缺失和属性缺失的表示。显式选择使约束可见,采用时读取所用编译器版本的选项说明,不把归档某个版本的默认值视作永恒规则。TSConfig 参考
项目引用描述构建依赖;被引用项目的配置及声明产物需满足 build mode 的要求。打包器可能只转译语法,tsc --noEmit 等检查需要单独执行。构建通过、类型通过和代码规范通过各自报告。
以下是两种执行目标的配置起点,分别放在各叶子项目,按编译器、宿主和依赖版本调整。它们没有在本页新建项目运行。浏览器项目由打包器处理模块,检查阶段不输出文件:
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "Bundler",
"jsx": "react-jsx",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noEmit": true
},
"include": ["src"]
}Node ESM 项目可以选择编译后执行。包声明 "type": "module",相对 import 采用输出后可解析的路径,例如源码写 import { run } from './run.js',并由 NodeNext 模式核对:
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"types": ["node"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"rootDir": "src",
"outDir": "dist"
},
"include": ["src"]
}Node 的目标 JavaScript 能力仍需符合所选运行时。浏览器 Bundler 允许的路径不保证能直接交给 Node;Node 直接运行 TS 的限制也不同于 tsc 输出后执行。库发布另需声明文件、公开出口和消费者测试,不能直接套用应用配置。模块解析模式
环境变量在什么阶段进入产物
环境输入通常是字符串。端口要解析为有界整数,URL 要解析并核对协议,必需秘密缺失时应在接收流量前失败。不要用无意义默认值掩盖生产配置遗漏。
浏览器公开变量在构建中可能被内联,之后更换服务器环境变量不会自动改已生成 JavaScript。Vite 的 VITE_ 与 Next 的 NEXT_PUBLIC_ 属于各自接口,公开前缀中的值能被客户端取得。服务器密钥保持在服务器运行边界。
例如用 Zod 在服务入口解析配置,把未经检查的 process.env 留在边界。后续模块接收解析后的配置对象,避免每次再读字符串:
import { z } from 'zod';
const envSchema = z.object({
PORT: z.coerce.number().int().min(1).max(65535).default(3000),
DATABASE_URL: z.string().min(1),
PUBLIC_ORIGIN: z.url().refine(value => new URL(value).protocol === 'https:'),
});
export const config = envSchema.parse(process.env);这是启动校验片段。数据库 URL 的协议、目标和秘密管理仍由数据库接线规定;不要把完整失败输入写入日志。开发 HTTP origin 可用独立开发配置处理,生产规则保持明确。
金额怎样保持精确
JavaScript number 使用二进制浮点表示,许多十进制小数无法准确表示。加一个 epsilon 只能针对有限舍入现象,无法建立财务精度。可用固定最小单位的整数,或从十进制字符串建立十进制库对象。
// decimal.js 的教学片段:输入从十进制字符串进入。
import Decimal from 'decimal.js';
const price = new Decimal('19.95');
const subtotal = price.times('3');
const due = subtotal.toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toFixed(2);精度位数、舍入模式、舍入时机和货币单位共同构成规则。传输和存储使用可保留该规则的表示,避免先 Number(...) 再试图恢复已损失精度。格式化可将准确十进制字符串分为整数与小数处理,并测试大值;Intl.NumberFormat 不承担内部记账精度保证。decimal.js
日期、时刻与区域
一个时刻指向时间线上位置,日历日期如生日可能不对应唯一时刻,某地区“每天九点”还依赖时区与夏令时。UTC 时间戳适合保存时刻,业务区域和日历规则需要另行保留。
不要通过固定偏移量推导所有地区日期,也不要把 YYYY-MM-DD 的业务日期随意转成午夜 UTC。输入、存储、比较、显示分别声明解释。日期工具和时区插件的具体支持随版本核查;本页保留归档 date-fns、时区工具的分工,不采用未经本次确认的版本锁定。
工具函数和测试怎样选择
工具库减少重复实现,但深拷贝、相等、去重、排序和防抖各有语义。对象按引用相等还是内容相等,取消防抖是否丢弃尾部工作,Unicode 文本按字节、码点还是字素分割,都需要按任务选择。
测试可分别检查纯规则、模块装载、环境校验和真实依赖。Vitest、Jest 与 node:test 的具体选择由宿主和资产决定;DOM 模拟器无法证明浏览器布局、焦点或媒体行为。归档工具排行、版本和下载量留作历史选择材料,正文不声称已经跑过一套新项目。
最后更新于