Aspnetcore: Publish TypeScript @types packages for Blazor JavaScript Interop

Created on 8 Feb 2020  路  7Comments  路  Source: dotnet/aspnetcore

Is your feature request related to a problem? Please describe.

There are methods that can be called when using Blazor JS interop: https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interop?view=aspnetcore-3.1#invoke-net-methods-from-javascript-functions

However, using these methods in the JS project can be a guessing exercise because the API is barely documented, especially when using TypeScript which requires type declarations to be defined.

Describe the solution you'd like

Example TypeScript interface declaration for Instance method call thing in Blazor JS interop:

interface dotNetHandler {
    invokeMethodAsync<T>(methodName: string, ...args): Promise<T>;
}

A new package on npm @types/blazor or @types/blazor-js-interop or something like that should be published with all type information for using Blazor JavaScript Interop

Additional context

In my experience, that window.DotNet is a mystery because invokeMethodAsync is always undefined there for some reason. So please add the TypeScript API documentation via @types packages.

affected-few area-blazor enhancement severity-major

All 7 comments

@ryanelian thanks for contacting us.

We'll look into this issue and add prioritize it appropriately.

We've moved this issue to the Backlog milestone. This means that it is not going to happen for the coming release. We will reassess the backlog following the current release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

Would it be then OK, to pusblish the basic shape of the interop interface based on the source of the extension project to the https://github.com/DefinitelyTyped/DefinitelyTyped project?
I can see there is a reason this question was asked, presuming the TypeScript support in the VS/VSCode.
With a basic shape like that one:

declare module DotNet {
    /**
     * Invokes the specified .NET public method synchronously. Not all hosting scenarios support
     * synchronous invocation, so if possible use invokeMethodAsync instead.
     *
     * @param assemblyName The short name (without key/version or .dll extension) of the .NET assembly containing the method.
     * @param methodIdentifier The identifier of the method to invoke. The method must have a [JSInvokable] attribute specifying this identifier.
     * @param args Arguments to pass to the method, each of which must be JSON-serializable.
     * @returns The result of the operation.
     */
    function invokeMethod<T>(assemblyName: string, methodIdentifier: string, ...args: any[]): T;
    /**
     * Invokes the specified .NET public method asynchronously.
     *
     * @param assemblyName The short name (without key/version or .dll extension) of the .NET assembly containing the method.
     * @param methodIdentifier The identifier of the method to invoke. The method must have a [JSInvokable] attribute specifying this identifier.
     * @param args Arguments to pass to the method, each of which must be JSON-serializable.
     * @returns A promise representing the result of the operation.
     */
    function invokeMethodAsync<T>(assemblyName: string, methodIdentifier: string, ...args: any[]): Promise<T>;
    /**
     * Represents the .NET instance passed by reference to JavaScript.
     */
    interface DotNetObject {
        /**
        * Invokes the specified .NET instance public method synchronously. Not all hosting scenarios support
        * synchronous invocation, so if possible use invokeMethodAsync instead.
        *
        * @param methodIdentifier The identifier of the method to invoke. The method must have a [JSInvokable] attribute specifying this identifier.
        * @param args Arguments to pass to the method, each of which must be JSON-serializable.
        * @returns The result of the operation.
        */
        invokeMethod<T>(methodIdentifier: string, ...args: any[]): T;
        /**
         * Invokes the specified .NET instance public method asynchronously.
         *
         * @param methodIdentifier The identifier of the method to invoke. The method must have a [JSInvokable] attribute specifying this identifier.
         * @param args Arguments to pass to the method, each of which must be JSON-serializable.
         * @returns A promise representing the result of the operation.
         */
        invokeMethodAsync<T>(methodIdentifier: string, ...args: any[]): Promise<T>;
    }
}

one could achieve everything expected when writing some advanced interop to enahnce Blazor with the client features. Instead of writing using loosened strict types withany in my code, I could just use typed instance:

class BeforeUnload {
  private instance?: DotNet.DotNetObject;

  ...

  addEventListener(instance: DotNet.DotNetObject) {
    this.removeEventListener();
    this.instance = instance;
    window.addEventListener("beforeunload", this.beforeUnloadHandler, false);
  }

and then I would simply use those 2 istance methods and those 2 static methods that way:

await this.instance.invokeMethodAsync<UserAction>("FetchUserAction", this.instance);
this.instance.invokeMethod<BeforeUnloadEvent>("OnBeforeUnload", e);
DotNet.invokeMethod<UserAction>("UserActionTracker", "TrackEvent", userActionResult);
await DotNet.invokeMethodAsync<UserAction>("UserActionTracker", "TrackEvent", userActionResult);

thanks!

Thanks for sharing this, @ryanelian.
The reason we've put this into the Backlog is not because this would not add value. We do agree that this would add value, it's just in contrast with the rest of the work we plan to do for the 5.0 release this doesn't meet the bar. As I've commented earlier, we will reconsider this in the future. For now, feel free to promote your type definition so people can use it and simplify usage of these APIs from TypeScript.

Thank you for explaining the reason this issue is punted to backlog and I totally understand.

I also agree that this feature does not reach the bar compared to other larger issues when it comes to polishing Blazor for upcoming .NET 5 release. (*cough* CTRL + dot automatic code completion still does not work in .cshtml / .razor files *cough*)

That said, it pains me that a feature (Blazor JS Interop) of a web framework made by Microsoft is barely usable in the IDE made by Microsoft when targeting a language (TypeScript) made by Microsoft unless the user writes some glue code themselves.

Can't you guys ask some TypeScript devs over at Microsoft to publish a rudimentary / five-minutes @types package for this particular feature please? :)

@ryanelian I'll make one and we will ask for review, sure thing!

DefinitelyTyped/DefinitelyTyped#42392

Was this page helpful?
0 / 5 - 0 ratings