Allow object types to have property-like associated types
See original GitHub issueEdit: Add static Type
variant for classes, make abstractness a little clearer, clarify things.
This has probably already been asked before, but a quick search didn’t turn up anything.
This is similar, and partially inspired by, Swift’s/Rust’s associated types and Scala’s abstract types.
Rationale
- In complex structures like in virtual DOM components/nodes and in graphs, where there are numerous constraints to check, but they would get cumbersome in a hurry to force off onto the user.
In dynamic imports, where you never have the module namespace itself until runtime, yet you still want to be able to use types defined within it.Edit: Already addressed elsewhere.- In types where there’s a lot of optional parameters, it’d be easier and more flexible to label which ones you’re defining as part of the type.
- In types where you want to specify a single optional parameter, and the required ordering requires you to specify some that you don’t want to specify, that would get boilerplatey in a hurry. I’ve experienced this personally on multiple occasions.
- It would allow fully typing namespaces and named module imports without hard-coded compiler handling.
Proposed Syntax/Semantics
- Each interface and object type may have a number of associated types within it.
- Associated types are checked for assignability like any other usual property, except they live in a different “namespace” from properties. In particular, the type must be assignable to the target’s type.
- To access an associated type, you use
TypeName.Type
, whereType
is the name of an associated type.- For sugar and namespace compatibility,
object.Type
is equivalent to(typeof object).Type
- For sugar and namespace compatibility,
- To expect an interface with an associated type, you use
Foo & {type Type: Value}
orFoo with <Type: Value>
. - To expect an object with an associated type, you use
{type Type: Value}
. - To declare an abstract associated type, you use
type Type: *
within the interface or object type. - To declare a non-abstract associated type, you use
type Type: Default
within the interface or object type. - To constrain an abstract associated type, you use
type Type: * extends Super
. - Associated types may be inherited from other interfaces and/or object types.
- Namespaces’ types are modified to include the exported types as associated types.
- Classes may also define associated types, optionally with visibility modifiers.
- Associated types may have defaults, in case they aren’t defined or further constrained later.
- Constraining an associated type with an existing default removes the default if and only if the existing constraint is not assignable to the new constraint. For example,
{type Foo: string | number = string} & {type Foo: string | number}
is assignable to{type Foo: string}
, but{type Foo: string | number = string} & {type Foo: number}
is not.
- Constraining an associated type with an existing default removes the default if and only if the existing constraint is not assignable to the new constraint. For example,
Here’s what that would look like in syntax:
// Interfaces
interface Foo {
type Type: *; // abstract
type Sub: * extends Type; // abstract, constrained
type Type: Default;
type Type: * extends Type = Default; // late-bound default
}
// Objects
type Foo = {
type Type: Foo,
}
// Classes
abstract class Foo {
// Note: outer class *must* be abstract for these, and the keyword is required.
abstract type Type: *; // abstract
private abstract type Sub: * extends Type; // abstract, constrained
protected abstract type Type: * extends Type = Default, // late-bound default
// Note: outer class *may* be not abstract for these.
type Type: Default;
private type Type: Default;
// Declare an associated type in the class
// Note: type must not be abstract.
static Type: Foo;
}
Emit
This has no effect on the JavaScript emit as it is purely type-level.
Compatibility
- This is purely additive, making no observably incompatible changes beyond possibly different error messages.
- This has no impact on any existing JavaScript-related proposal.
Other
- It may slow down the type checker a little initially when namespaces are unified, but two optimization points are available, which would recover most of the perf hit, if not all:
- Associated types could be stored in a per-interface type map.
- The list of associated types could be initially stored as
undefined
to avoid generating a large number of empty arrays.
- It should have little effect on editor tooling.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:54
- Comments:34 (12 by maintainers)
Top Results From Across the Web
Understanding protocol associated types and their constraints
In case you're not familiar, Movie and Song conform to Item because Swift structs automatically get a memberwise initializer to satisfy the init ......
Read more >Protocol with associated type as property - Stack Overflow
2 Answers 2 · I think your answer needs some improvements. Notice that I want to have Item in Owner and Item in...
Read more >Documentation - Object Types - TypeScript
Optional Properties. Much of the time, we'll find ourselves dealing with objects that might have a property set. In those cases, we can...
Read more >4. Object Types - iOS 8 Programming Fundamentals with Swift ...
But I have not yet described how object types in general really work. ... Now let's talk about how to extract the associated...
Read more >Getting started with associated types in Swift Protocols
Associated Types in Swift allow you to reuse code. ... protocol Collection { associatedtype Item var count: Int { get } subscript(index: ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
We NEED this.
Any status update? Could still totally use this myself for the reasons explained in the initial comment, too.