Skip to content

Conversation

@nikeokoronkwo
Copy link
Collaborator

@nikeokoronkwo nikeokoronkwo commented Jul 12, 2025

Fixes #402
Fixes #409
Fixes #411

This PR adds support for classes and interfaces in TypeScript for the Dart JS Interop Interface Generator.

Interfaces and Classes in TS are mapped to Dart extension types, following Dart's new JS Static Interop for JS. Constructors are generated by default for classes (defaulting to a zero-parameter constructor if not specified). Unless denoted by hierarchy, all extension types by default have JSObject as their rep type and implement JSObject

  1. Constructors are mapped to Dart constructors on an extension type
  2. Methods are mapped to Dart methods
  3. Properties are mapped to Dart properties
  4. get and set accessors are mapped to getters and setters in Dart
  5. callable interfaces are mapped to extension types with a call parameter, so they can be called in Dart.
  6. indexable interfaces and classes are mapped to override the operators of [] and []= (the second is only if the indexer member is not readonly), so they can be indexed in Dart.
  7. readonly members are mapped to only getters rather than normal fields
  8. Only public members are generated, as those are the only members that can be accessed by Dart's JS Interop layer.
  9. Alternate constructors are mapped to factory constructors with different names in the extension type
  10. Overriden methods are marked with @redeclare
  11. Nullable Methods are represented as getters that return JSFunction? (once dart-lang/sdk#54557 lands, we will have it with generics)
  12. Extended classes are represented with the extendee being implemented as well as being it's representation type
  13. Implemented classes and extended interfaces are represented with the extendees/implementees being implemented on the extension type.

Therefore, the following

interface Shape<TMetadata = any> {
    readonly id: string;
    name: string;
    area(): number;
    area(unit: 'cm2' | 'in2'): string;
    onUpdate?(prev: Shape<TMetadata>): void;
}
declare class ShapeImpl<TMeta = any> implements Shape<TMeta> {
    readonly id: string;
    name: string;
    /* other decls in Shape */
    metadata?: TMeta;
    constructor(name: string, type?: 'circle' | 'rectangle' | 'polygon');
    constructor(config: Shape<TMeta>);
    get location(): string;
    set location(value: string);
    static getById(id: string): ShapeImpl;
    toString(): string;
}

Maps to this

import 'dart:js_interop' as _i1;
import 'package:meta/meta.dart' as _i2; // needed for @redeclare

extension type Shape<TMetadata extends _i1.JSAny>(_i1.JSObject _) implements _i1.JSObject {
  external String get id;
  external String name;
  external double area();
  @_i1.JS('area')
  external String area$1(AnonymousUnion unit); // AnonymousUnion defined afterwards
  external JSFunction? get onUpdate;
}

extension type ShapeImpl <TMeta extends _i1.JSAny>(_i1.JSObject _) implements Shape {
  external ShapeImpl(String name, [AnonymousUnion$1 type]);
  external factory ShapeImpl.unnamed$1(Shape<TMeta> config);
  @_i2.redeclare
  external String get id;
  external String name;

  external TMeta? metadata;
  external String get location;
  external set location(String value);
  external static ShapeImpl getById(String id)
  /* other decls in Shape */
}

For more examples, check out the added tests classes_input.d.ts and interfaces_input.d.ts as well as their expected results for more

Other features, such as an adjusted AST, filtering mechanism, and more have been implemented.

This PR also adds support for a typeMap to allow reusage of certain types with associated declarations such as unions

Copy link
Contributor

@srujzs srujzs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work!!! This is super cool to see - great PR description and tests!

@kevmoo
Copy link
Member

kevmoo commented Jul 17, 2025

good to merge @srujzs ?

Copy link
Contributor

@srujzs srujzs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you were able to unify the various class and interface code, awesome!

@srujzs srujzs merged commit 0a16c09 into dart-lang:main Jul 17, 2025
16 checks passed
copybara-service bot pushed a commit to dart-lang/sdk that referenced this pull request Jul 22, 2025
Revisions updated by `dart tools/rev_sdk_deps.dart`.

ai (https://github.com/dart-lang/ai/compare/61ba1ea..40607dc):
  40607dc  2025-07-21  Jacob MacDonald  rename ElicitationHandler.reject to ElicitationHandler.decline (dart-lang/ai#240)
  ec6efa4  2025-07-21  Kostia Sokolovskyi  Fix ping request handling from non-dart clients. (dart-lang/ai#239)
  00889b4  2025-07-17  Jacob MacDonald  release dart_mcp version 0.3.2 (dart-lang/ai#237)
  5e93ef4  2025-07-17  Jacob MacDonald  Deprecate EnumSchema and JsonType.enumeration (dart-lang/ai#236)
  66af21b  2025-07-17  Jacob MacDonald  fix the firstMatchOnly and matchRoot schemas to be booleans (dart-lang/ai#235)
  141fbe1  2025-07-17  Jacob MacDonald  release dart_mcp 0.3.1 (dart-lang/ai#234)
  ce519e8  2025-07-17  Jacob MacDonald  Add flutter driver tool (dart-lang/ai#223)
  3bf650e  2025-07-16  Jacob MacDonald  add completions support to the prompts example (dart-lang/ai#233)
  aed93b4  2025-07-16  Jacob MacDonald  Deprecate the WithElicitationhandler interface (dart-lang/ai#231)
  01cf3d4  2025-07-16  Jacob MacDonald  Require dart_mcp version 0.3.1 (dart-lang/ai#232)
  5c28640  2025-07-16  Jacob MacDonald  add a sampling example (dart-lang/ai#230)
  df0c4f1  2025-07-16  Jacob MacDonald  add elicitation example, fix some issues with the elicitation APIs (dart-lang/ai#229)

http (https://github.com/dart-lang/http/compare/2d9681d..4a90d16):
  4a90d16  2025-07-21  Alex Li  [cronet_http] Update Cronet dependencies version (dart-lang/http#1796)
  5c06c6c  2025-07-18  Brian Quinlan  Prepare to release cronet 1.4.0 (dart-lang/http#1794)
  8c49ef5  2025-07-18  Hossein Yousefi  [cronet_http] Upgrade jni and jnigen to 0.14.2 (dart-lang/http#1793)
  ca07b4c  2025-07-17  Brian Quinlan  Add request cancellation to cupertino_http (dart-lang/http#1779)
  984cc43  2025-07-15  Brian Quinlan  Fix a bug where ConnectionException.toString didn't stringify NSError (dart-lang/http#1785)

protobuf (https://github.com/dart-lang/protobuf/compare/04bd6ac..4916e6f):
  4916e6f  2025-07-21  Ömer Sinan Ağacan  CI: Test PRs and commits to all branches, instead of just master (google/protobuf.dart#1029)
  a9822d8  2025-07-16  Devon Carew  prep for publishing protobuf 4.1.1, protoc_plugin 22.5.0 (google/protobuf.dart#1025)
  38f1549  2025-07-15  Devon Carew  update the generator to emit formatted files (google/protobuf.dart#1020)

test (https://github.com/dart-lang/test/compare/2be5ca0..c201cc9):
  c201cc98  2025-07-21  Nate Bosch  Expand Analyzer constraints to allow 8.x (dart-lang/test#2518)

tools (https://github.com/dart-lang/tools/compare/a4335eb..2a2a2d6):
  2a2a2d61  2025-07-17  Nikechukwu  [code_builder] Set `external` and `static` in correct order (dart-lang/tools#2120)

web (https://github.com/dart-lang/web/compare/7e0853d..767151e):
  767151e  2025-07-21  Nikechukwu  [web_generator] Bug Fixes in Entrypoint `gen_interop_bindings.dart` (dart-lang/web#423)
  1f80532  2025-07-21  Nikechukwu  [interop] Support `typeof` type declarations (dart-lang/web#417)
  affce52  2025-07-17  Kevin Moore  generator: drop build bits. Not used. (dart-lang/web#419)
  0a16c09  2025-07-17  Nikechukwu  [interop] Support Classes and Interfaces (dart-lang/web#415)

Change-Id: I9fbe6d7c15d63b19e45829628e7c5dfb3e87ca6c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/441820
Auto-Submit: Devon Carew <devoncarew@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Interop Gen: Support Overloaded Constructors Interop Gen: Support Classes Interop Gen: Support Interfaces

3 participants