2 回答
TA贡献1853条经验 获得超6个赞
我不认为你想做什么是可能的。您要求打字稿更改变量类型作为副作用。但这会带来各种并发症。
如果mapData函数有条件地运行怎么办?
const mapped: Mappable = JSON.parse(data);
if (Math.random() > 0.5) {
mapData(mapped); // mapped is now of type Mapped
}
// What type is `mapped` here?
或者,如果您在转换之前传递对此对象的引用怎么办?
function doAsyncStuff(obj: Mappable) {}
doAsyncStuff(mapped)
mapData(mapped)
// Then later, doAsyncStuff(obj) runs but `obj` is a different type than expected
我认为你能在这里得到的最接近的是一个转换为中间类型的类型保护,它支持转换前类型和转换后类型的联合,你可以在其中实际进行转换。
interface A {
foo: string
}
interface B {
foo: string
bar: string
}
interface A2B {
foo: string
bar?: string
}
function transform(obj: A): obj is B {
const transitionObj: A2B = obj
transitionObj.bar = "abc" // Mutate obj in place from type A to type B
return true
}
const obj: A = { foo: 'foo' }
if (transform(obj)) {
obj // type is B in this scope
}
obj // but obj is still type A here, which could lead to bugs.
但是,如果您实际上在该条件之外使用objas 类型A,那么这可能会导致运行时错误,因为类型是错误的。所以带有副作用的类型保护函数也是一个非常糟糕的主意,因为类型保护可以让你覆盖类型脚本的正常输入。
我真的认为你已经在这里做了最好的方法,特别是如果输出类型与输入类型不同。将新对象不可变地构造为新类型。
const mapped: Mapped = toMappedData(json);
如果性能或内存是一个大问题,那么您可能不得不为此牺牲类型安全。编写健壮的单元测试,将其投射到任何单元测试,添加关于那里发生的事情的非常突出的评论。但是除非您一次处理数百 MB 的数据,否则我敢打赌这真的没有必要。
TA贡献1900条经验 获得超5个赞
我目前所做的方式是:
type KeyList = 'list' | 'of' | 'some' | 'keys';
// Merged the types to keep the code a little shorter
// Also makes clear, that I don't alter the type's structure
interface MyType<M ext boolean = true> {
source: { [K in KeyList]: SomeNestedObject },
sourceOrder: (M ? SomeNestedObject : (KeyList | SomeNestedObject))[];
}
function mapData(data: MyType<true>): MyType {
const { source, sourceOrder } = data.sourceOrder
for (let i = 0; i < sourceOrder.length; i++) {
if (typeof sourceOrder[i] == 'string') {
sourceOrder[i] = source[sourceOrder[i]];
}
}
return (data as unknown) as MyType;
}
const json: MyType<true> = JSON.parse(data);
const mapped: MyType = mapData(json);
// mapped now references json instead of being a clone
我不喜欢这种方法的地方:
它不是类型安全的。打字稿无法检查我是否正确地改变了类型
因此,我必须转换为未知,这并不理想
json
类型不那么严格。可能会对代码建议产生负面影响该功能有一个
side effect
以及一个return type
(排他性side effect
或return type
更清洁)
添加回答
举报