I am looking to create a reusable RxJS operator that can map from object T to Q. This will be used to convert dates formats. T & Q are therefore different types but only in regard to the properties, the keys remain the same for both.
我希望创建一个可重复使用的RxJS操作符,可以从对象T映射到Q。这将用于转换日期格式。因此,T&Q是不同的类型,但仅就属性而言,两者的键保持相同。
I think for the most part I am there but running into some typing issues that I can't resolve.
我想在很大程度上我在那里,但遇到了一些我无法解决的打字问题。
export function convertDateTimeToluxon<T extends object, Q extends Record<keyof T, any>>(): (source: Observable<T>) => Observable<Q> {
return (source: Observable<T>): Observable<Q> => source.pipe(
map((object: T): Q => {
const convertedObj: Q = {} as Q;
Object.keys(object).forEach((key: string) => {
const typedKeyT: keyof T = key as keyof T;
if(Datetime.isDateTime(object[typedKeyT])) {
convertedObj[typedKeyT] = DateTime.fromISO(object[typedKeyT]);
} else {
convertedObj[typedKeyT] = object[typedKeyT];
}
})
return convertedObj;
})
)
}
}
The issue occurs on the 2 assignment lines
问题发生在两个分配行上
convertedObj[typedKeyT] = DateTime.fromISO(object[typedKeyT]);
convertedObj[typedKeyT] = object[typedKeyT];
转换对象[类型键T]=DateTime.FromISO(对象[类型键T]);转换对象[类型键T]=对象[类型键T];
Where TypeScript is complaining that T[key of T] is not assignable to Q[key of T]
- I assume this is to do with the any type in the record at the top?
TypeScrip抱怨T[T的键]不能分配给Q[T的键]-我假设这与顶部记录中的Any类型有关?
Answer - this is what i have come up with for the time being, sure it could be improved!
回答--这就是我目前所想出来的,当然可以改进!
Part of this is taken from geoffreys answer below
这部分摘自Geoffreys下面的回答
export function convertDateTimeToLuxon<T extends Record<keyof T, any>, Q extends Record<keyof T, any>>(): (source: Observable<T>) => Observable<Q> {
return (source: Observable<T>): Observable<Q> => source.pipe(
map((object: T): Q => {
const convertedObj: Q = {} as Q;
Object.keys(object).forEach((key) => {
const typedKeyT: keyof T = key as keyof T;
if (DateTime.isDateTime(object[typedKeyT])) {
convertedObj[typedKeyT] = DateTime.fromISO(object[typedKeyT]) as Q[keyof T];
} else {
convertedObj[typedKeyT] = object[typedKeyT];
}
})
return convertedObj;
})
)
}
更多回答
优秀答案推荐
T extends Record<PropertyKey, any>
solves it. (I also removed unnecessary annotations in a few places):
T扩展记录
解决它。(我还删除了几处不必要的注释):
function convertDateTimeToluxon <T extends Record<PropertyKey, any>, Q extends Record<keyof T, any>>() {
return (source: Observable<T>): Observable<Q> => source.pipe(
map((object: T) => {
const convertedObj = {} as Q;
Object.keys(object).forEach((key: string) => {
const typedKeyT = key as keyof T;
if(Datetime.isDateTime(object[typedKeyT])) {
convertedObj[typedKeyT] = DateTime.fromISO(object[typedKeyT]);
} else {
convertedObj[typedKeyT] = object[typedKeyT];
}
})
return convertedObj;
})
);
}
I'm not sure why this works though. I noticed that object
was generally requiring more annotations.
不过,我不确定这为什么会奏效。我注意到该对象通常需要更多的注释。
更多回答
Hi thanks for replying, that has solved the issue with the second assignment, but the first one is still having issues due to the following. Type 'DateTime' is not assignable to type 'Q[keyof T]'.
DateTime is assignable to the constraint of type Q[keyof T], but Q[key of T] could be instantiated with a different subtype of constraint any
I also realised with the help of your answer that i could use T extends Record<keyof T, any>
嗨,谢谢你的回复,这已经解决了第二个作业的问题,但由于以下原因,第一个作业仍然有问题。类型‘DateTime’不可赋值给类型‘Q[key of T]’。DateTime可分配给类型Q[key of T]的约束,但Q[key of T]可以用约束any的不同子类型实例化。我也通过您的回答认识到,我可以使用T扩展记录
Solved the 2nd part of the issue, thanks for the help - put me in the right direction
解决了问题的第二部分,谢谢你的帮助--把我带到正确的方向
Yes it's funny that something like T extends Record<keyof T, any>
works but I think it looks too clever for what it does. If a generic is not needed I think it should not be used as it can confuse maintainers. TS is complex enough as it is.
是的,有趣的是,像T扩展记录这样的东西起作用了,但我认为它看起来太聪明了。如果不需要泛型,我认为不应该使用它,因为它会让维护人员感到困惑。尽管如此,TS已经足够复杂了。
Where do you import DateTime from?
从哪里导入日期时间?
Its from Luxon, we have api data that sends dates in one format and i want a tidy way to convert any of these dates into a Luxon Datetime so that everything inside the application has a standardised way of dealing with / displaying dates. We are explicitly transforming these on a service by service basis at the moment. And this is an attempt to explore making our lives a little easier and having one pipeable operator we can use wherever we need to do this.
它来自Luxon,我们有以一种格式发送日期的API数据,我想要一种整洁的方法来将这些日期转换为Luxon日期时间,以便应用程序内的一切都有一个标准化的处理/显示日期的方式。目前,我们正在逐个服务的基础上明确地转变这些服务。这是一种尝试,让我们的生活变得更容易,有一个管子操作器,我们可以在任何需要这样做的地方使用。
我是一名优秀的程序员,十分优秀!