ioredis
ioredis copied to clipboard
`pipeline()...exec()` returns `Promise<[error: Error | null, result: unknown][] | null>`
Hey there,
while migrating to 5.x I noticed that our pipelines have ts errors now. Consider this example:
cacheAndExpireValue(value: string): Promise<string | null> {
return cluster
.pipeline()
.getset("someKey", value)
.expire("someKey", 42)
.exec()
.then((result) => {
if (result[0][0]) {
throw result[0][0];
}
return result[0][1];
});
}
I'd expect that result[0][1] should always be a string (correct me if I am wrong please) but exec() returns Promise<[error: Error | null, result: unknown][] | null> thus the need to cast the result manually, otherwise we get a compiler error since we collide with the return type of cacheAndExpireValue():
TS2322: Type 'Promise<unknown>' is not assignable to type 'Promise<string | null>'.
  Type 'unknown' is not assignable to type 'string | null'.
    Type 'unknown' is not assignable to type 'string'.
If I am right and we can only ever expect string here, why not let exec() return Promise<[error: Error | null, result: string][] | null> or, if I am wrong, at least be able to use a generic like exec<T>(): Promise<[error: Error | null, result: T][] | null> (or similar)?
Yes, result[0][1] should be of type string, and result[1][1] should be of type number, but because of TypeScript restrictions, we have to make them unknown. This makes pipeline() a bit inconvenient but I haven't thought of any solutions to improve this.
Could you elaborate a bit on those typescript restrictions you're referring to?
@schw4rzlicht since the pipeline has a dynamic list of commands in it, and each command has a different return type, it is not possible to correctly type the response array from the pipeline execution. Hence the need for the pipeline creator (your code) to interpret the results based on what is in the pipeline.
Should be possible to type correctly with the pipeline array style, i think it's also possible with chaining if each call modified the context