I am now using a Visitor pattern where I have 2 visitors using the same interface returning T. It basically looks like the schema below, but my visitor returns something.
I would like to change the return type of one of my visitor to return a Promise.
Should I create a new interface for this issue?
If you want to make use of async/await
, I think it makes sense to create a new interface called AsyncVisitor
. Every visitor you implement should, in a sense, be thought of as its own "virtual" function on an enumeration of types. However, in JavaScript, Function
and AsyncFunction
are two inherently different types of functions, where the latter may suspend execution and must always return a Promise
. Therefore, it doesn't make sense to have one visitor interface to represent both regular and async functions.
While you could hypothetically implement your promise-based Visitor as just Visitor<Promise<T>>
and async/await
will still work, your interface would then mix and treat Function
and AsyncFunction
as interchangeable types, which can be unexpected if you're doing some kind of metaprogramming.
In other words, I think your interfaces should look something like this:
interface Visitor<T> {
visitElementA(e: ElementA): T;
visitElementB(e: ElementB): T;
}
interface AsyncVisitor<T> {
visitElementAAsync(e: ElementA): Promise<T>;
visitElementBAsync(e: ElementB): Promise<T>;
}
interface Element {
accept<T>(v: Visitor<T>): T;
acceptAsync<T>(v: AsyncVisitor<T>): Promise<T>;
}