Closed orta closed 1 year ago
I just found out that VSCode TypeScript supports inline type hints, the gray types there are not written by user but elicited by the IDE
It doesn't work for const
for some reason but it does for let
... It of course works if you use only VSCode during your video lectures. Rust is a language that is unusable for me without inlay hints, TypeScript seems to benefit from those too, it might be hard to get used to it at first because they might add noise you don't want.
All TypeScript and Deno settings.json for inlay hints
{
// For TypeScript
"typescript.inlayHints.variableTypes.enabled": true,
"typescript.inlayHints.parameterNames.enabled": "all",
"typescript.inlayHints.functionLikeReturnTypes.enabled": true,
"typescript.inlayHints.parameterTypes.enabled": true,
"typescript.inlayHints.propertyDeclarationTypes.enabled": true,
"typescript.inlayHints.enumMemberValues.enabled": true,
"typescript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": false,
"typescript.inlayHints.variableTypes.suppressWhenTypeMatchesName": false,
// Color settings
"workbench.colorCustomizations": {
"editorInlayHint.foreground": "#7e7e7e",
"editorInlayHint.background": "#ff000000"
},
// For deno
"deno.inlayHints.variableTypes.enabled": true,
"deno.inlayHints.parameterNames.enabled": "all",
"deno.inlayHints.functionLikeReturnTypes.enabled": true,
"deno.inlayHints.parameterTypes.enabled": true,
"deno.inlayHints.propertyDeclarationTypes.enabled": true,
"deno.inlayHints.enumMemberValues.enabled": true,
"deno.inlayHints.parameterNames.suppressWhenArgumentMatchesName": false,
"deno.inlayHints.variableTypes.suppressWhenTypeMatchesName": false,
}
It doesn't work for
const
for some reason
If you write e.g. const foo = "bar"
then the type is "bar"
so the inlay hint isn’t shown since it would be redundant. I think the same is true for new Class()
because there again, the type is obvious. Outside of that you should still get inlay hints for const
.
the teaching community is changing to be more video focused
I’m probably in the minority on this but I always felt like video was the wrong medium for teaching programming, because there’s very little temporal component to it. Sure, it takes time to enter code, but that’s entirely mechanical; if I could beam all the code I need into the computer at once with just my thoughts, I would. Thus why AI tools like GitHub Copilot are successful.
Video coding tutorials make me think of those old boring YouTube “tutorials” where it’s just someone typing stuff into Notepad for 10 minutes - just give me the text file to read myself! 😅
Then again, I’ve always learned better from API references than coding tutorials (which tend to just make me impatient), so yeah.
Yep, the inlay hints feature in editors is what this feature on the playground and the vscode extension linked use, the current support doesn't handle the types of sorts of introspection I was showcasing though (and for me are mostly noise).
Hah, everyone trying to drag my proposal off-topic! I also prefer text, but the availability + accessibility of youtube (and maybe tiktok? though I struggle to imagine it's a great learning tool for depth) have changed what its like at the beginning of expertise even if it's not really doing much for the intermediate to experts for a topic!
Hah, everyone trying to drag my proposal off-topic!
Yep, sorry about that. 😅
I just used the Playground and it’s neat that the ^?
syntax already works there.
[Edit: slightly off-topic, apologies] For written content (printed books, blog posts, etc.), I’d love to additionally be able to state the inferred type and have a tool check that it’s correct – e.g.:
const str = "Hello" as const;
// ^? const str: "Hello"
Alternative 1 – shorter:
const str = "Hello" as const;
// ^? "Hello"
Alternative 2 – prefix:
// @inferred-type: "Hello"
const str = "Hello" as const;
There is support for that as an eslint plugin, https://github.com/JoshuaKGoldberg/eslint-plugin-expect-type/pull/47
This would be a VS Code or other editor thing, since there's (AFAIK) nothing TS Server could tell the editor to do here that would make this happen automatically.
VS Code would need a minor change to always ask for inlay hints, but I'd expect the core of the support to live in provideInlayHints
in TSServer which is what does all the heavy lifting for this in here
So we chatted about this in our editor sync. We all love and use query comments (// ^?
) in the playground, and some of us have it installed in VS Code itself.
Here's some of what came out of the conversation - some of it just describing our own next steps, and some of it feedback that might or might not be interesting/useful
One really cool idea we had is whether it could make sense for the extension to work on other languages. There's no reason query comments have to be specific to TypeScript and JavaScript. Is there a world where this extension could operate on multiple languages?
VS Code already provides a command for requesting hover (see an example here). An extension could just leverage that instead of talking directly to TSServer.
Unfortunately there's public no mechanism for asking for the current token scope
to see whether a position falls in a comment. I'm pretty sure _workbench.captureSyntaxTokens
is not meant to be public. But I believe the playground doesn't really care if something really falls in a comment anyway:
The comment pattern could be special-cased on a per-language basis - but so many languages use //
that they'd all benefit from just that.
So the TL;DR? No for now - but we're happy to revisit in the future.
We do think that there's a really cool opportunity for the extension to generalize to more languages if it's something you'd be interested in.
++ to improving the extension discoverability && adding additional language support -- a simple step could be TS-ish languages like Astro components :)
comment queries for rust-analyzer when 👀
comment queries for rust-analyzer when 👀
With the linked code:
return vscode.commands.executeCommand<vscode.Hover[]>(
'vscode.executeHoverProvider',
editor.document.uri,
editor.selection.active);
The extension generalizes to any language which has a hover provider. The trick is just finding the comments.
comment queries for rust-analyzer when 👀
With the linked code:
return vscode.commands.executeCommand<vscode.Hover[]>( 'vscode.executeHoverProvider', editor.document.uri, editor.selection.active);
The extension generalizes to any language which has a hover provider. The trick is just finding the comments.
Is there an LSP version of this that generalizes to use in other editors like Neovim, etc? Something that @Princesseuh was thinking of as an approach.
Every editor has its own way of hooking into LSP, so, every editor will have (or not have) a way to call the language servers its interacting with. I can't really offer any recommendations to that end.
err I'm thinking of it more from the "if I, the LSP, see a comment with this structure, I'll add an inline hint that shows the type of the identifier the comment "points" to"
That's basically what this issue was asking for (though, TS does not use LSP), with the caveat that there is no LSP API which allows you to arbitrarily tell the client to render inlay hints; only an API where the client can request them and the server answers (which TS already implements).
I see, so this is more explicitly an editor tooling feature for requesting inlay hints that should work with any LSP that implements inlay hints?
It's a request that tsserver implement a new feature that does (or does something like) inlay hints for // ^?
, and that VS Code supports it, however that might work. This issue has nothing to do with the LSP as TypeScript's tsserver does not implement the LSP.
All very great arguments which I fundamentally agree with!
I think exploring converting the twoslash extension into a more generalized 'query comments' system is totally doable, and once that's got some steam, chat with the vscode team about whether the idea is good for upstreaming further down the line. Thanks for the feedback!
Maybe it means helping out https://marketplace.visualstudio.com/items?itemName=YiJie.vscode-comment-queries /cc @NWYLZW
Happy to close as a NOOP on the TS side
comment queries for rust-analyzer when 👀
With the linked code:
return vscode.commands.executeCommand<vscode.Hover[]>( 'vscode.executeHoverProvider', editor.document.uri, editor.selection.active);
The extension generalizes to any language which has a hover provider. The trick is just finding the comments.
Now I have implemented support for both Golang and Python using this feature.
It is true that the current TypeScript LSP cannot provide more structured data, which is a difficult point for plugin development. Providing more support in this aspect would be very helpful for me.
@NWYLZW where can I find this implementation? (esp for Golang)
@NWYLZW where can I find this implementation? (esp for Golang)
https://marketplace.visualstudio.com/items?itemName=YiJie.vscode-comment-queries
https://github.com/NWYLZW/vscode-comment-queries/blob/main/langs/golang/main.go
Suggestion
Should add an inline recommendation to editors what the type is at
msg
.I think there are a significant amount of new TypeScript users who are learning the language through video tools/tutorials. Probably much more than we expect. Lots of the folks teaching use this syntax via a vscode extension I wrote a few years back.
I initially punted on discussing internally about upstreaming it into TSServer, but I've slowly turned around on the idea as it feels like the teaching community is changing to be more video focused. So, I think it's worth the complexity, at least to bring it up.
🔍 Search Terms
inline comments show types messages print types twoslash
✅ Viability Checklist
My suggestion meets these guidelines:
⭐ Suggestion
TSServer already has inlay hint support for other features, so it would be expanding support, perhaps that means at parse/bind time checking comments for
// ^?
and caching their locations, then printing the results when an editor asks for hints in a particular range.The current code simply uses the same kind of regex as the TSC tests
```ts export function activate(context: vscode.ExtensionContext) { const provider: vscode.InlayHintsProvider = { provideInlayHints: async (model, iRange, cancel) => { const offset = model.offsetAt(iRange.start); const text = model.getText(iRange); const results: vscode.InlayHint[] = []; const m = text.matchAll(/^\s*\/\/\s*\^\?/gm); for (const match of m) { if (match.index === undefined) { return; } const end = match.index + match[0].length - 1; // Add the start range for the inlay hint const endPos = model.positionAt(end + offset); const inspectionPos = new vscode.Position( endPos.line - 1, endPos.character ); if (cancel.isCancellationRequested) { return []; } const { scheme, fsPath, authority, path } = model.uri; const hint: any = await vscode.commands.executeCommand( "typescript.tsserverRequest", "quickinfo", { _: "%%%", file: scheme === 'file' ? fsPath : `^/${scheme}/${authority || 'ts-nul-authority'}/${path.replace(/^\//, '')}`, line: inspectionPos.line + 1, offset: inspectionPos.character, } ); if (!hint || !hint.body) { continue; } // Make a one-liner let text = hint.body.displayString .replace(/\\n/g, " ") .replace(/\/n/g, " ") .replace(/ /g, " ") .replace(/[\u0000-\u001F\u007F-\u009F]/g, ""); if (text.length > 120) { text = text.slice(0, 119) + "..."; } const inlay: vscode.InlayHint = { kind: 0, position: new vscode.Position(endPos.line, endPos.character + 1), label: text, paddingLeft: true, }; results.push(inlay); } return results; }, }; ```📃 Motivating Example
I think there are 2 main uses for this, and I've framed the initial part of this issue as being about education because that's what changed my opinion. The other part is that it is genuinely useful to pull out types while you are working on a more complex type, in which case twoslash comments act like a way of seeing your work in progress on complex types.
For example when I built a "wordle" in the type system, each type I created I would create an example of it in use and print it in order to see how types flow through the system. You can see a few left in here: https://t.co/OmXoSdi1Y1
Downsides
There are a few interesting downsides to the syntax, which I think are fine but at east worth highlighting:
Extensions
We could also add support for drilling into the types: