如何在TypeScript中用Immer转换不同泛型参数的Data类型?
问题:使用Immer安全转换泛型Immutable类型的类型参数
类型定义与需求
首先有如下类型定义:
type Data<T> = Immutable<{ data: T }> const a: Data<number> = { data: 0 }
需要用immer的produce函数,将变量a从Data<number>类型转换为Data<string>类型。
直接调用的类型错误
尝试直接调用produce会触发类型报错:
produce(a, (d) => { d.data = d.data.toString() })
报错信息:Type 'string' is not assignable to type 'number',原因是回调中试图给Data<number>的data字段赋值字符串,类型不匹配。
不符合类型安全的“合法”写法
但下面这段代码却能通过TypeScript的类型检查,这明显不合理:
produce<Data<number>, Draft<Data<string>>>(a, (d) => { d.data = d.data.toString() }) // 结果类型:Data<number>
问题在于:
- 返回值的类型被推断为
Data<number>,但实际data字段已经被修改为字符串,类型和实际值完全不符 - 回调参数
d的data字段被错误识别为string类型,和原始值的number类型矛盾,完全违背了类型安全的原则
当前可行但不严谨的方案
目前找到的可行写法是用any做类型断言:
produce<Data<string>>(a as any, (d) => { d.data = d.data.toString() })
需要注意:TypeScript会把回调里的d.data识别为string类型,但实际上原始值是number,这段代码能运行只是因为toString()方法在number和string类型上都存在,属于偶然可行的情况,并不严谨。
疑问
请问在TypeScript中,有没有更合理、真正符合类型安全的实现方式?
内容的提问来源于stack exchange,提问作者Aleksandar Dimitrov
相关产品推荐
相关产品推荐

