Comments (7)
But what if I have a middleware which usage only makes sense after some filtering was done and it also modifies the context, extending it's type?
Then this filtering can narrow down the type to a custom, more narrow type by using a type predicate with bot.filter
.
Since there are multiple bot.use
statements that mutate the bot object's type, we cannot do this any other way. The only solution would be to move away from mutating statements entirely, and use a purely declarative syntax for middleware, but this is much harder to use, looks less familiar, and will generally alienate away newcomers.
People have suggested less explicit ways of changing the bot object, but that's just type casts in disguise so I won't ship that stuff.
from grammy.
Then this filtering can narrow down the type to a custom, more narrow type
Yes I can narrow down middleware input context. But how to properly type context modified by middleware?
Since there are multiple bot.use statements that mutate the bot object's type
Honestly, I didn't understand what do you mean. For me the solution is the matter of adding second type param to Middleware, adding types to NextFunction and proper typings for use:
use<T extends C>(...middleware: Array<Middleware<C, T>>): Composer<T> {
const composer = new Composer(...middleware);
this.handler = concat(this.handler, flatten(composer));
return composer;
}
But that's may be naive.
from grammy.
Then this filtering can narrow down the type to a custom, more narrow type
Yes I can narrow down middleware input context. But how to properly type context modified by middleware?
Using a type predicate. Look:
const t: Composer<T> = composer.filter((ctx): ctx is T => {
ctx.prop = value;
return true;
})
In TypeScript, type predicates always are implicit type casts.
Since there are multiple bot.use statements that mutate the bot object's type
Honestly, I didn't understand what do you mean. For me the solution is the matter of adding second type param to Middleware, adding types to NextFunction and proper typings for use:
use<T extends C>(...middleware: Array<Middleware<C, T>>): Composer<T> { const composer = new Composer(...middleware); this.handler = concat(this.handler, flatten(composer)); return composer; }
This code does not type-check. You will have to add an explicit type cast to the implementation.
But that's may be naive.
It is not. This has been discussed before, and we were considering to introduce bot.cast<T>
that simply casts the context type. However, type casting is unsafe, so we should ideally make it as explicit as possible. Adding a new method to hide away the type cast (or---even worse---secretly performing type casts internally in bot.use
) increases the chance of bugs, so it simply makes bot code worse.
If you want to perform type casts, simply do them explicitly:
const narrow = (composer as Composer<T>).use(async (ctx, next) => {
ctx.prop = value;
await next();
});
from grammy.
Using a type predicate. Look:
Mutating inside filter is by any means ugly, I think you'd agree. But at least thanks for a workaround.
This code does not type-check. You will have to add an explicit type cast to the implementation.
I don't think so. My assumption is that we can add second type to middleware and type NextFunction properly. Again, have you checked the link I provided? Can it possibly be implemented the way they did?
or---even worse---secretly performing type casts internally in bot.use
Why secretly? It's inferred, yes, but without dirty tricks.
from grammy.
Using a type predicate. Look:
Mutating inside filter is by any means ugly, I think you'd agree. But at least thanks for a workaround.
I do agree, but you were explicitly asking for filtering and type casting in one, so if there were any meaningful filtering condition in the code, it would look muss less like abuse.
This code does not type-check. You will have to add an explicit type cast to the implementation.
I don't think so. My assumption is that we can add second type to middleware and type NextFunction properly. Again, have you checked the link I provided? Can it possibly be implemented the way they did?
I have, and we have played around with similar implementations, but the code rapidly gets messy with fully declarative middleware systems. If you have 50 handlers installed after 10 plugins and 5 custom pieces of middleware, you'll end up with deep nesting or lots of helper variables. If you can draft an implementation for a middleware system that is better, please share it here, but especially @wojpawlik tried many options and so far there has not been a convincing result.
or---even worse---secretly performing type casts internally in bot.use
Why secretly? It's inferred, yes, but without dirty tricks.
Casting with as
would happen at some point inside the library and the developer would not know this. It is better to cast explicitly.
from grammy.
grammY is already pushing TypeScript to its limits.
grammY's Composer
could allow sub-trees with independent ctx
, but we couldn't think of any practical use-case.
The very foundation of middleware trees prevents us from doing use(...): asserts this is Composer<???>
:
Lines 225 to 226 in 4280050
from grammy.
Related Issues (20)
- Update to oak new `request.body` API HOT 4
- (bug) memory leak HOT 6
- Stripe Pre-Checkout Timeout Error while making a Test Payment from Telegram Bot HOT 2
- parse_mode doesn't work with editMessageText HOT 5
- baseApiUrl not working HOT 1
- Publish `grammY` to JSR respository HOT 18
- feat: add a warning in debug mode upon "Call to 'getMe' failed! (401: Unauthorized)" that the bot token is incorrect HOT 9
- 1.22.0 broke existing code type check HOT 7
- [feature] How do I listen for every messages in a group chat? HOT 2
- Can't deploy conversations plugin on Cloudflare Workers HOT 1
- Property 'wait' does not exist on type 'ConversationControls'.ts(2339) HOT 2
- feat: ctx.message.message_thread_id presumably should not be | undefined in message:is_topic_message HOT 6
- [Proposal] Expose type FilteredContext. HOT 1
- HttpError: Network request for 'getMe' failed! HOT 5
- HttpError: Network request for 'sendMessage' failed! HOT 3
- Add error type to `GrammyError` HOT 2
- Problem with editing files (editMessageMedia and editMessageMediaInline) HOT 3
- menu plugin with multiple language translations error HOT 2
- Bot not full width on mobile HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from grammy.