0

I registered a RegisterAsyncJsObject in the CefSharp ChromiumWebBrowser. This creates an additional JavaScript object instance in the web browser which looks like this:

frame.openWindow(name, data);
frame.navigateToWindow(name, data);

It works great with plain JavaScript. I'm able to access to this object and the methods do their job.

Now I want to program against this object with TypeScript, but the TypeScript compiler doesn't know the types of that object. I tried to create a type definition file of that object, but it doesn't really work. it seems if I import a definition / declaration, what ever, it will override the 'frame' object.

Do you have any idea how to use that object in TypeScript ?

Do I really need to have a type definition for that object? And how does it really work?

Until now I just used TypeScript and already done type definitions, but didn't created definitions by my own.

Juergen Gutsch
  • 1,774
  • 2
  • 17
  • 28
  • you could just create a .d.ts files that extends the the frame interface with the extra methods. you can read more about open ended interfaces in typescript here(sample B) https://basarat.gitbooks.io/typescript/content/docs/types/interfaces.html – toskv Feb 16 '17 at 23:10
  • Thanks, I already tried it. How do I import the d.ts in a right way without overriding the instance of that frame object? – Juergen Gutsch Feb 17 '17 at 07:14
  • typescript interfaces are open ended, if you make a new interface with the same name (and module etc) it will just add the new methods you define to the existing one. – toskv Feb 17 '17 at 07:37
  • the import is the issue here. see the answer below – Juergen Gutsch Feb 17 '17 at 07:44

1 Answers1

3

If frame doesn't yet have an existing type, you can define your own:

interface MyFrame {
    //fill in the `any` and `void` types as appropriate
    openWindow(name: any, data: any): void; 
    navigateToWindow(name: any, data: any): void;
}

//if frame is initialized somewhere else:
declare let frame: MyFrame;

//if you want to initialize it here:
let frame: MyFrame = //some initialization code

If frame has an existing type, say HTMLFrameElement from lib.d.ts, then you can add an additional interface to extend the existing one. This is known as declaration merging:

interface HTMLFrameElement {
    openWindow(name: any, data: any): void; 
    navigateToWindow(name: any, data: any): void;
}

This can be done either in a regular Typescript file (.ts) or in a definition file (.d.ts).


You can include the interface + declaration in the current file, and that should allow you to use these methods. If you want to place it in an external file, and in order to let the compiler know about the file, do one of the following:

  • Include it in the project's tsconfig.json
  • Import it into each referencing file with import "/myfile"
Zev Spitz
  • 13,950
  • 6
  • 64
  • 136
  • Many Thanks. If it's in a separate file (.ts or .d.ts) how do I import this? import { frame }... creates a new variable, which overrides my object, even the declaration in the same file were I use the frame. import * as frame ... wrapps another object around it. No import works in the IDE, but the TypeScript compiler still misses it – Juergen Gutsch Feb 17 '17 at 07:10
  • @JuergenGutsch Do you have a `tsconfig.json` which includes this file? That should be enough. Which IDE are you using? – Zev Spitz Feb 17 '17 at 07:33
  • @JuergenGutsch You should be able to use `import "/myfile"`. – Zev Spitz Feb 17 '17 at 07:39
  • That's it. Just to tell the compiler where the file is. Many thanks. I use Visual Studio Code. It finds the file because it is somewhere in the project folder. – Juergen Gutsch Feb 17 '17 at 07:41
  • great thanks :) That's what i was looking for. I don't want to add too much to the tsconfig. so this seems to be a clean and easy way :) – Juergen Gutsch Feb 17 '17 at 07:50
  • @JuergenGutsch Keep in mind that if you use `import` you'll have to do it in every single file that references these methods. Also, RE _I don't want to add too much to the tsconfig_ -- are you worried about performance? I don't think this is an issue. Or are you worried about making the `tsconfig.json` too complex to understand? You don't necessarily need to specify each and every file in `tsconfig.json`; you can configure directories to exclude or include. See [here](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html). – Zev Spitz Feb 17 '17 at 07:54
  • Thanks for the reminder and your support. In this specific case, 'frame' is just used in a single file. So it seems to be fine like this. – Juergen Gutsch Feb 17 '17 at 07:59
  • @JuergenGutsch Because if it's only used in a single file, it might be simpler to put the interface in the file directly (outside of any namespaces), instead of a separate file + import. – Zev Spitz Feb 17 '17 at 08:01
  • i tried it. If I do like this, the let frame: MyFrame; overrides the already existing instance coming from the webview. – Juergen Gutsch Feb 17 '17 at 08:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/135933/discussion-between-zev-spitz-and-juergen-gutsch). – Zev Spitz Feb 17 '17 at 08:04