Skip to content
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

Improved TypeScript types for TokenizerAndRendererExtension #3228

Open
Cipscis opened this issue Mar 15, 2024 · 2 comments · May be fixed by #3230
Open

Improved TypeScript types for TokenizerAndRendererExtension #3228

Cipscis opened this issue Mar 15, 2024 · 2 comments · May be fixed by #3230
Labels

Comments

@Cipscis
Copy link

Cipscis commented Mar 15, 2024

What pain point are you perceiving?.
I've recently started writing custom some TokenizerAndRendererExtension code in a personal project, using TypeScript, and I've found it slightly annoying to work with the way the extension's renderer method receives a Token.Generic even though (I assume) it should be possible to know that it receives a token of the type returned by its tokenizer method.

Current solutions involve either using type assertions to tell the TypeScript compiler that I know more about the structure of these tokens than TypeScript is telling me, or validating the shape ourselves (which adds additional work to rendering that AFAIK shouldn't be necessary so isn't ideal). Both approaches require manually keeping type assertions or checks in the renderer updated whenever the shape of the token changes in the tokenizer.

On a related but less important note, it could be nice to also enforce the constraint that the extension's name string must be the same as its token's name string.

Describe the solution you'd like
Currently, marked provides a Token.Generic type for general-use tokens, which looks like this:

interface Generic {
	[index: string]: any;
	type: string;
	raw: string;
	tokens?: Token[] | undefined;
}

This allows access to any properties, but they are typed unsafely as any so it's up to the consuming code to decide how to deal with that.

I think this could be resolved by allowing TokenizerAndRendererExtension to take a generic type parameter, defining the type of token it uses internally. I believe this could be written in such a way as to allow that generic type parameter to be inferred through the value returned by the tokenizer function. The parameter could have a default type that would maintain the current any behaviour, so existing code that references this type without a generic type parameter would still work in the same way.

However, this approach would also necessarily make a few other internal types (in particular TokenizerExtension and RendererExtension) generic as well. Without having attempted to implement this, I'm not sure if there would be additional complexity spreading to other types. I don't have any knowledge currently of marked's codebase, aside perhaps from having viewed the type declaration files it ships with.

@UziTech
Copy link
Member

UziTech commented Mar 15, 2024

I like that idea. If you want to create a PR it would be very appreciated 😁👍

@Cipscis
Copy link
Author

Cipscis commented Mar 15, 2024

I'll see if I can have a crack at it over the weekend

@Cipscis Cipscis linked a pull request Mar 15, 2024 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants