Skip to content

☂️ [Extension type] Language feature docs #4177

@itsjustkevin

Description

@itsjustkevin

Copied from #5446 and closed that issue to consolidate tracking
This issue outlines the plan for the new extension types language feature in 3.3.

Summary

Extension types are an abstraction that lets you write a new, static-only interface for an existing type. This could mean expanding functionality by declaring new members, or redefining the type's existing members, or enforcing discipline by choosing not to define certain members so that functionality can't be used for instances of the new type.

Extension types enable new JSInterop features, but enable other uses cases as well. This documentation will define their syntax, functionality, and use cases. The full description of JSInterop functionality will reside with the JSInterop documentation (#5438)

Evaluation

  1. The Extension types page will go under the Language (tour) umbrella in the side nav, under the Classes & objects section, after the Extension methods page.

  2. Outline: (some of this information may end up naturally settling in different parts of the page; this is the full topic coverage laid out sequentially)

  • Intro

    • What is an extension type
    • Why use an extension type (point to / elaborate in Use cases section)
      • Why they're not wrapper classes (run time / expensive / performance / identity conflicts)
      • Why they're not extension methods (client side / imports / "bleeds" into all representation type objects)
      • If these descriptions get too long for the intro, save full explanations for corresponding Use cases (but still mention "they're not wrapper classes / extension methods" in the intro)
  • Syntax / Functionality

    • Declaration
      • Identical to class
        • Scope and this have the same interaction as with classes
      • Can declare type parameters
      • Representation type
        • Primary constructor, (<type> <name>)
          • (don't actually say "primary constructor", proposal is not accepted yet)
          • Other syntax (<type> _) used in JS interop -- not sure what to call it or if it has an application outside of JS interop
        • Extension type is considered to have a final instance variable of that name and type
        • Also possible to use another extension type as a representation type, but marginal use / not useful
      • Implements clause
        • Clarify difference with class implements
        • Introduces a subtype relationship
        • Can implement another extension type
    • Body
      • Constructor (like a class, optional)
        • Non-primary constructors (e.g. in the body, if any) must declare the instance variable defined in the representation type declaration (covered in Syntax > Declaration) in their initializer list (or however the constructor is defined)
      • Members
        • Can’t declare instance fields
          • Except external because those are just getters / setters for external objects
        • Can contain methods, operators, getters and setters
          • Access the representation type using the representation name (named in declaration) as a getter
        • Method declaration
          • Not declaring a member of the representation type means it will not be available to extension type instances
          • @redeclare -- super-interface / sub-interface member declaration (so, implements cases only)
    • Usage
      • Extension type member invocations
        • I think "receiver" is the terminology for the instance object of an extension type (?)
        • Like e = <ext type>(<representation object>)
          • So e is the "receiver" here
        • Can invoke members with either property extractions (getters or tearoff) or method invocation (e.<member>())
  • Type stuff

    • Explain type at runtime / static behavior
    • is / as casting behavior
      • dynamic type test / cast "unwraps" the representation type, unsafe
        • (maybe this belongs in the intro to emphasize the "unsafe" aspect users need to be aware of)
    • "Transparency" -- conceptual agreement that you have a "transparent" extension type if you implement the representation type
      • but casting can still unwrap non-transparent extension types because the representation type is always accessible at runtime.
  • Use cases (code examples)

    • Extended interface on an existing type
      • "server side" extension method approach
      • expanding functionality
    • Different interface
      • "newtype" approach
      • restricting functionality
    • Bridge to other languages
      • JSInterop / other FFI
      • tells compiler to recognize and treat external members as native JS methods if they have the JSObject representation type
    • Reuse code
      • "inheritance / multiple inheritance" approach
      • Extension type with super-interface that's another extension type
    • Adapt typing properties / safer types
      • "covariance / invariance" approach
      • makes dynamically-checked covariance subtype problems compile time errors instead of undetectable runtime errors

Resources

Metadata

Metadata

Assignees

Labels

a.languageRelates to the Dart language toure3-weeksComplete in < 4 weeks of normal, not dedicated, workfix.examplesAdds or changes examplemeta.umbrellaCollects multiple related issuesp1-highMajor but not urgent concern: Resolve in months. Update each month.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions