-
Notifications
You must be signed in to change notification settings - Fork 908
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Missing type definitions on ctx.message #1388
Comments
I'm glad you asked! I explained it a few times already, but I think about this a lot, so I have a better understanding each time. TypeScript is trying to tell you that not every message is a text message. There are several ways you can proceed in Telegraf 4:
What could Telegraf 5 do?
|
You could also use ascription if you're totally sure about the message type, and this brings you zero cost at the runtime. import { Message } from 'typegram'
// ...
bot.on('text', (ctx) => ctx.reply((ctx.message as Message.TextMessage).text))
// ... I believe this is where TypeScript takes over JavaScript. An explicit type guard is necessary to force you to consider those corner cases. |
Hi @wojpawlik, |
For now, I suggest copying it. |
I don't have a good idea for a name, but thanks for the clarification. Exporting it for usage in interfaces would be amazing. Thank you very much. |
Hello, can someone explain (or add more details to examples) how to use WizardScene and read user input for specific step. Because a lot of examples uses message.text (for example https://stackoverflow.com/questions/55749437/stage-enter-doesnt-start-the-wizard) but it does not work with typescript. Because if you just started to learn telegraf and without googling this issue #1388 - this is really tricky to understand. At this moment i found only one simple solution, but i am not sure that is correct. async (ctx) => {
await ctx.reply('Step 3');
if (ctx.message && 'text' in ctx.message) {
console.log(ctx.message.text);
return ctx.wizard.next();
} else {
return ctx.reply('Please input your details');
}
}, |
okay thanks the information |
Any updates on this issue? |
I got no idea thats going on with my issue, even after seeing a relation between mine and this issue. Thats a plan of maintainers to deal with a lack of typings. I tried to solve that properly somehow in my case, but didnt find any good way by myself |
@atassis For your specific case, the correct way to handle it is: bot.on("message", (ctx, next) => {
if ("contact" in ctx.message) {
console.log(ctx.message.contact);
}
}); TS is (not) telling you that all message updates are not contact messages. When you filter using this if-check, TS knows exactly what kind of message update you're dealing with. |
I was using the spreaded variable in the condition and that didn't specify the exact type somehow, "god works in mysterious ways". |
Since people are going to find this issue, the new way to filter updates is like so: import { message } from "telegraf/filters";
bot.use(ctx => {
if (ctx.has(message("text")) {
ctx.message.text // works!
}
}); These filters are also usable in bot.on(message("text"), ctx => {
ctx.message.text // works!
}); Both You can also now filter for things you could not before, like import { editedMessage, channelPost } from "telegraf/filters";
bot.on(channelPost("video"), ctx => {
ctx.channelPost.video // works!
}); This is available since 4.11.0 — I strongly recommend reading the release notes. We will also keep working on making filters more powerful in v4, and the ctx object even more easier to use in v5. See also: #1471 |
would it be possible to show a typed example of:
bot.on('message', (ctx) => {
}) the correct typing of ctx has so far eluded me |
Code from @MKRhere. Sorry for asking a silly question.
If I would like to pass the ctx, what type should I use for bot.on(message('text'), async (ctx) => {
await handleRequest(ctx);
});
const handleRequest = async (ctx: ?) => {
console.log(ctx.message?.text)
}; |
import type { Update, Message } from "telegraf/types";
const handleRequest = async (ctx: Context<Update.MessageUpdate<Message.TextMessage>>) {
// ...
} |
for custom Context, lets say MyContext where custom
Here ts complains about session does not exists. |
@djeks922 I cannot reproduce this. Can you show more surrounding code? |
|
fyi |
I'm not good at typescript so, maybe is there some option to pass MyContext as generic T to .has or similar way? |
'NarrowedContext<Context, MessageUpdate<Record<"voice", {}> & VoiceMessage & AddOptionalKeys>>' Thanks beforehand, I hope I was able to explain the problem |
@djeks922 I was able to recreate your problem. Make export interface MyContext extends Context {
- session?: SessionData;
+ session: SessionData | undefined;
} I cannot explain why this works, but it does. TS is black magic some times. |
It means that property session has to be defined, while with question mark operator it doesn't have to |
@atassis Of course I know that. I wrote the type that narrows down |
The
message
property ofctx
has a lot of missing type definitions which don't follow the official ones.The line of code causing the error was this one:
bot.on("message", (ctx) => ctx.reply(ctx.message.text));
The bot should reply with the text you send to him.
The text was updated successfully, but these errors were encountered: