-
Couldn't load subscription status.
- Fork 741
Description
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
-
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.
-
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
thishave the same interaction as with classes
- Scope and
- 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
- Primary constructor,
Implementsclause- Clarify difference with class
implements - Introduces a subtype relationship
- Can implement another extension type
- Clarify difference with class
- Identical to
- 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
externalbecause those are just getters / setters for external objects
- Except
- 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,implementscases only)
- Can’t declare instance fields
- Constructor (like a class, optional)
- 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
eis the "receiver" here
- So
- Can invoke members with either property extractions (getters or tearoff) or method invocation (
e.<member>())
- Extension type member invocations
- Declaration
-
Type stuff
- Explain type at runtime / static behavior
is/ascasting 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)
- dynamic type test / cast "unwraps" the representation type, unsafe
- "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
externalmembers as native JS methods if they have theJSObjectrepresentation 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
- Extended interface on an existing type
Resources
- Spec
- Diagnostic messages:
@redeclareannotation: [Extension type] Add a@redeclareannotation sdk#53121- Original /language issue: Extension types language#2727
- /sdk tracking: Implement Extension Type Feature sdk#52684