JXA-userland / JXA

JavaScript for Automation(JXA) packages for TypeScript/Node.js.
MIT License
424 stars 21 forks source link

Support for non-core applications #5

Closed havardh closed 5 years ago

havardh commented 6 years ago

Hi. Great work 👍

This issue might be more of a how do you do this in TypeScript, but here it goes. I think that the my use case would be interesting to others, so at least we could end up with some documentation.

I would like to add type declarations for 'non-core' types. Core as I understand it being the applications bundled with osx and defined in types/src/core . And they are manually added as return types for the Application function, right?

As an example I would like to add declarations for Emacs. I'm able to generate the .d.ts files from the .sdef file. But I'm not sure how include this file to work well with the rest of the jxa types.

Is there a way to "inject" this into the current setup or would it require changes?

Furthermore do you see a way of automating this. E.g. automatically discovering .sdef's in the Application folder and generating .d.ts files on the fly? Or would it be better to include these types in a package under the @jxa org?

LoganDark commented 6 years ago
const emacs = <EmacsType> Application('Emacs')

?

havardh commented 5 years ago

@LoganDark your proposal gives me the following error:

[ts]
Type 'typeof Application & _StandardAdditions & AnyValue' cannot be converted to type 'Emacs'.
  Property 'close' is missing in type 'typeof Application & _StandardAdditions & AnyValue'.
(alias) Application(name: string): typeof Application & Application._StandardAdditions & Application.AnyValue (+25 overloads)
export namespace Application
LoganDark commented 5 years ago

Does your type extends App?

Where App is:

https://github.com/JXA-userland/JXA/blob/4aa1185f423473212cd03160778b0fb549f6e8e2/packages/%40jxa/types/src/Application.d.ts#L29

havardh commented 5 years ago

Ah, thanks @LoganDark 👍

I got the following snippet to work:

import "@jxa/global-type";
import {Emacs} from "./types/Emacs";
import Application from "@jxa/types/src/Application";

type App = typeof Application & Application._StandardAdditions & Application.AnyValue;

const emacs = <App & Emacs> Application("Emacs");

Where types/Emacs is the .d.ts made by @jxa/sdef-to-dts.

@azu: Feel free to close this issue or advice me on how this could fit into this library.

azu commented 5 years ago

Maybe, we can provide more generics way.

import "@jxa/global-type";
import {Emacs} from "./types/Emacs";
// Maybe, types export `Application`
import { Application } from "@jxa/types";
// TODO: `Application` support Custom Application by generics.
const emacs = Application<Emacs>("Emacs");
// Emacs is `Application & Application._StandardAdditions & Application.AnyValue & Emacas`;

Implemention:

/**
 * Pass custom Application type as generics
 * Return Application's StandardAdditions & T type
 */
declare function Application<T>(name: string): typeof Application & Application._StandardAdditions & Application.AnyValue & T;
azu commented 5 years ago

I've submit PR #6

azu commented 5 years ago

@havardh I've published 1.2.0 Please try to use this :)

https://github.com/JXA-userland/JXA/releases/tag/v1.2.0

import { Application } from "@jxa/types";
import {Emacs} from "./types/Emacs";
const emacs = Application<Emacs>("Emacs");
havardh commented 5 years ago

@azu Great, I've tested this on 1.2.1 and it works for my use case.

This brings me to the next part of my questions, can we make it more ergonomic to add these types? E.g. an additional repo with these custom types, or a simple npx @jxa/sdef-to-dts Emacs.app => Emacs.t.ds.

azu commented 5 years ago

@havardh Interesting. If we get sdef file from app name, we can implement this feature. (I don't know if that's is possible or impossible.)

Please create another issue.