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

feat: scoped platform API types #45

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

NathanWalker
Copy link

See RFC for details. In summary:

Historically NativeScript has always provided platform API types on the global scope, for example:

// available anywhere you type
NSString. 
java.

Progressive ideas around handling platform API types have emerged in 2022 among TSC discussions.

Here are the biggest three options in consideration.

A. import from runtime packages

import { NSString } from '@nativescript/ios'

import { java } from '@nativescript/android'

The types could ship with the runtimes themselves either directly or via proxy to @nativescript/types.

B. import from existing types packages explicitly

import { NSString } from '@nativescript/types-ios'

import { java } from '@nativescript/types-android'

B. import specifiers

See how Node is handling here, eg ... from 'node:fs'

Prior Art: nodejs/node#43413

// esm:
import { NSString } from 'native:Foundation';
// commonjs:
const NSString = require('native:Foundation').NSString;

For third party vendors:

// Objective C/Swift
import { LOTAnimationView } from 'native:Lottie';

// Java/Kotlin
import { LottieAnimationView } from 'native:com.airbnb.lottie';

@cla-bot cla-bot bot added the cla: yes label Dec 26, 2022
@rigor789
Copy link
Member

Thanks for bringing this up as an RFC! There are many related topics that this can start a conversation around.

I'm not entirely sold on such a big shift (with either option). I feel like it's a big mental shift to require thinking about imports, plus all content that includes example code would technically become incorrect even more so than it currently is (lot's of tns-core-modules/* out there in the wild).

The other side to this is more on the technical level. Types currently reflect how the runtimes work, moving types into deeper imports would require changes to both the build tooling and the runtimes to support, since this wouldn't purely be a typing/TypeScript change. Supporting both current and the proposed syntax at the same time would increase the maintenance overhead of the runtimes.

However, I think our types could be optimized, especially on android. Pairing them down to less, and perhaps more concise/better TypeScript declarations would be a huge step forward. For example, we could start dropping all but latest API versions from the types package (iOS already does this). This would greatly reduce the overhead of all these dts files in editors. Another point of optimization would be to correctly group namespaces/modules instead of re-declaring them multiple times (on the dts-generator side).

Currently, the dts-generator outputs in this format:

declare module android {
  export module R { /* ... */ }
  /* ... */
}
declare module android {
  export module accessibilityservice { /* ... */ }
  /* ... */
}
declare module android {
  // ...
}
declare module android {
  // ...
}

Notice how we have multiple declare module android { blocks - these could all be grouped together.


On Android/java code is organized into packages, however symbols can be "exported" at any level and in those cases you would be required to import from different levels individually.

import { LottieAnimationView } from 'native:com.airbnb.lottie';
import { LottieCallback } from 'native:com.airbnb.lottie.callback';

Not sure if this would be a "con", just thought I'd mention.


Finally, a few remarks/nits:

It's long been debated and even attacked as to whether platform API types should be on the global scope.

I haven't really noticed this being debated, though it does occasionally surprise people that they don't need to import anything to access android. for example.

This would improve developer experience and help the TSC optimize various compiler behaviors.

I think it would be useful to elaborate on how this would affect dx and what optimizations would be possible on the compiler level (I presume easier metadata filtering for example).

is it more clear or less clear

At first it feels less clear to me, however I'm open to try a minimal POC version (purely based on types, not necessarily functional) in my editor to feel it out.

@ammarahm-ed
Copy link

ammarahm-ed commented Mar 1, 2023

Has anyone thought about re-exporting globals as scoped imports? That would not require any changes in the runtime or build tooling plus allow us to migrate from global to scoped imports in a step by step process.

For example a module "ns-string"

export const NSString = globalThis.NSString;

declare module "ns-string" {
     NSString: globalThis.NSString
}

We can customize the metadata generators to generate these single module files for each api with the above format which can be imported in code editors.

And you can use it as

import { NSString } from "ns-string";

const val = NSString.alloc().init();

This would simplify metadata filtering a lot probably. And i think it's simple to do.

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 this pull request may close these issues.

3 participants