V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
V2EX  ›  Ketteiron  ›  全部回复第 12 页 / 共 38 页
回复总数  741
1 ... 8  9  10  11  12  13  14  15  16  17 ... 38  
1 月 6 日
回复了 FlashEcho 创建的主题 程序员 如何优雅地使用 zod
以 drizzle 的数据库 schema 为第一优先级,在此之上派生下一级的用于接口校验、表单验证的 schema 。
现代化的 typescript 工程,要严格遵守 DRY ,不允许在任何地方出现多次重复定义,分离数据库层与业务层实际上与复用逻辑并不冲突,没有写两遍的必要。
无论何时,应该只有一个唯一来源,应用于整个项目,包括前端以及所有中间件服务,并强制保证运行时类型与 ts 类型完全等同。

基于这个理论,不应该直接使用 createInsertSchema 和 createUpdateSchema ,因为它们也是在重复定义并不明确的类型,应该封装一个方法统一给所有下一级 schema 使用。

它可能长这样 const createSchema = (table,labels)=> createInsertSchema(table).pick(labels)
具体代码不贴了,有一些类型体操,需要保证输入限制以及 pick 生效

举个例子,我定义好一张表
export const userTable = pgTable('user', {
...baseTable,
username: varchar({ length: 32 }).notNull().unique(),
password: varchar({ length: 64 }).notNull(),
})
然后这么使用
export const userLoginSchema = createSchema(userTable, {
username: (s) => s.min(4),
password: (s) => s.min(6),
})
因为返回的是一个 zod 对象,可以按照业务逻辑进行 extend 不在数据库中的其他参数,或者根据业务进行覆盖

第一参数接收一个数据库表,以此限制第二参数输入的键名,value 是一个函数,参数是经过 drizzle-zod 生成后的 schema
drizzle-zod 会为 varchar({ length: 32 }) 这样的定义自动生成 z.string().max(32),但是它不会限制最小长度,因此派生的 schema 需要在原来基础上进行补充,或者也可以直接传入一个 zod 对象覆盖。

不应该对业务层暴露一大堆的 optional ,而是严格限定你只能传递什么东西过来,它要么必须有值要么禁止传递,从数据库层一层一层往下传递到所有涉及到的地方,一直到达前端表单,这才是 schema("契约")的正确用法之一。

还有个地方需要注意,这个 schema 不能直接在 monorepo 中被前端/中间件引入,因为包含完整的数据库模式以及用不到的大量运行时函数,直接 import 大概会打包出两百多 k ,需要使用 json-to-zod + zod-to-json(zod4 最新版已内置) 等变通方法,监听 schema 文件自动生成一个新文件并 export 给其他项目。当然因为无法序列化函数,所以 refine 等功能都用不了。

此外我对 createSchema 进行了大量改造,包括强制传递元数据,并在路由/表单通过包装 safeParseAsync 函数解析出适合人类阅读的提示信息:'用户名长度最低为 4 位'、'密码长度最低 6 位'、'缺少 xxx 字段'、'xxx 格式错误',其中'用户名'和'密码'就是我要求传递的提示文本,它同样只能定义一次,还可以进行 i18n 改造,所有其它信息可以通过遍历 code 、origin 、input 等进行填充,社区里大量使用的 zod i18n 库是一个不理想的变通方法,但图省事也可以去用。
1 月 5 日
回复了 ethusdt 创建的主题 JavaScript 你们 js 用过双等号吗
@shintendo #24 eslint 已经弃用了 allow-null ,可以传递一个对象例如 ["error", "always", {"null": "ignore"}] 进行排除。https://eslint.org/docs/latest/rules/eqeqeq
我认为 == null 是个不太好的编程习惯,带有隐式判断
我自己无论何时都会显式编写 if (x === null || x === undefined)
不过也没用上几次,在有了 ?. 和 ?? 后,几乎不存在需要使用 ==null 的场景
假榜,两个春熙路都没看见
2025 年 12 月 24 日
回复了 8675bc86 创建的主题 程序员 AI 是不是基本杀死了 blog
@Kirkcong #68 各大中小厂商的文档只能用狗屎来形容,如果再打开官方提供的 SDK 看一下源码更是不堪入目。
2025 年 12 月 24 日
回复了 jaydenWang 创建的主题 程序员 React 缺失的“M”层:我开发了 Zenith,重塑完整的 Model
const deps = getDeps.call(store, store);
这样的实现必须手动在 getter 写一次,@memo 指定依赖列表,完全依赖约定,把 react 的糟粕带了过来。

useStoreSelector 是通过猜测用户访问了什么属性调用 trackGetterAccess 增加引用计数,有多脆弱我就不说了,至少 StrictMode 会错误计数。此外没处理好竟态条件。

另外 View 层反向控制 Model 的缓存过于反模式,只要没有 React 组件在查看属性,就会直接删掉缓存。
Immer 混搭 weakMap 过于奇葩。

一堆 any ,看一半就没耐心看下去了。
函数式的重点在于不可变更新。

> 费力地模拟着面向对象
不费劲,闭包是穷人的对象。

你说对象=状态+行为

更准确地说
对象=原型链+状态+行为
闭包=状态+行为

get() 和 this 有本质上的区别,this 只会带来 bug 和心智负担。

> 它是“二等公民” :你必须显式地调用它 get(),而且它打破了 JS 引擎对 this 的自然优化。
这是我 2025 年听到最好笑的笑话,比这个还好笑 /t/1177228
2025 年 12 月 19 日
回复了 zhengfan2016 创建的主题 Vue.js 请问 vue3 的 onclick 和 @click 有什么区别
我有个不相关的问题,这位老哥会被疯狂 @吗?
https://www.v2ex.com/member/click
2025 年 12 月 18 日
回复了 MagicCoder 创建的主题 程序员 从已损坏的备份中拯救数据
不太可能是网络波动导致的,nfs 默认使用 tcp ,tcp 是解决网络不可靠的传输协议,要么完整地传输过去,要么抛出一个错误提示传输失败。
"Corrupted block detected"
"Restored data doesn't match checksum"
这已经说明了文件在存储前/后发生了变更,我是觉得你的内存或者硬盘至少坏了一个,另外系统卡死大概率是相同问题,全部排查一遍吧。
@yeqizhang #9 标准结论一直都有啊,用不用 jwt 只看需不需要 jwt 。
jwt 实际上是拿 cpu 解密开销换取数据库查询开销,为了安全性可能会双 token(15 分钟危险期) or 单 token+redis(秒级封禁)。除此之外有非常多的组合方法,但各有侧重点没有高下之分,软件开发不存在通用最优解。
2025 年 12 月 18 日
回复了 MagicCoder 创建的主题 程序员 从已损坏的备份中拯救数据
大概率内存出问题了,基本上 99%的文件静默错误来源于内存比特纠正失败。
生成的压缩包带上了错误的校验和,那肯定会失败,一开始就不存在正确的数据。再一次证明了 ECC 内存的重要性。
把建模从 interface 换成 schema 不就行了,与其从类型生成 runtime ,不如限制 runtime 并派生完全相同的类型。
类型生成 runtime 是有正当用途,某些框架例如 Vue 可以通过类型生成 runtime ,但是业务也这么干我感觉是歪门邪道。
这也是一个老生常谈的话题,我觉得所有尝试反射、保留元信息的做法都是错误的。
https://github.com/akutruff/typescript-needs-types
2025 年 12 月 12 日
回复了 nightl2018 创建的主题 程序员 中英文 prompt 对代码生成质量有影响吗?
agent 模式区别不大,对话会有影响,但非英语母语水平还是不建议用英文,除非你的中文水平也达不到中文母语平均水平
2025 年 12 月 11 日
回复了 hugozach 创建的主题 程序员 以前写 Python 被 go 鄙视;现在写 go 被 rust 鄙视...
@flytsuki 会被写 C 的鄙视
2025 年 12 月 11 日
回复了 cmos 创建的主题 程序员 要是用 Rust 就不会出问题了
@XIVN1987 写得差该漏还是漏,但相对来说几率小很多。js/py 很容易无意识写出导致内存泄漏的代码,其次是大量使用的依赖库本身也有很多内存泄漏。
2025 年 12 月 11 日
回复了 cmos 创建的主题 程序员 要是用 Rust 就不会出问题了
@XIVN1987 带 GC 的语言,屎山堆起来肯定会遇到内存泄漏,而且排查困难,有可能是狗屎业务代码引发的,有可能是底层框架/库引发的,还有可能是编译器/解释器自己的问题(点名 nodejs)。
2025 年 12 月 8 日
回复了 Kinnikuman 创建的主题 TypeScript 你们是怎么学习 typescript 的?
typescript 没有规范一说,因为随便一个特定场景都有十几种等价写法。
如果对 typescript 有兴趣,可以尝试下挑战一下
https://github.com/type-challenges/type-challenges
但这样的项目无法真正"教会"如何写 typescript 。
2025 年 12 月 6 日
回复了 Jony4Fun 创建的主题 信息安全 第一次遇到这么 bt 的问题,原来是 React 的漏洞
笑死了🤣可以评选今年最佳
2025 年 12 月 6 日
回复了 shakaraka 创建的主题 分享创造 在写 ts 项目的时候,被依赖注入烦到
@Chuckle 这些都可以用中间件实现,我感觉不到太大好处,还丢了类型安全。
当然,没有非常通用的库,对于不同场景下的用例可能需要手搓。
对象和参数就应该是不可变的,装饰器这套隐藏的风险太大,太过依赖"约定大于配置"。

而且这取决于底层用的框架是什么,nestjs 没得选,hono 之类的框架也没得选。

如果不用框架,我觉得显式编程对比装饰器多数情况下代码行数会更少,除非项目/库架构基于对象可变性。
1 ... 8  9  10  11  12  13  14  15  16  17 ... 38  
About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2731 Online   Highest 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 43ms · UTC 04:39 · PVG 12:39 · LAX 21:39 · JFK 00:39
♥ Do have faith in what you're doing.