ES8 Proposal: Optional Static Typing

Herby Vojčík herby at mailbox.sk
Sun Jul 19 21:44:18 UTC 2015


Two things:

I heard Gilad Bracha in ECOOP to say [paraphrase] "optional typing is 
great to help with documentation, and to help the tools; but it should 
not touch the runtime". This is what I take for my own as well, nicely 
said. Your overload proposition, though, changes the language so that 
this would need to touch the runtime. It seems there are two distinct 
view on bringing static typing in to dynamically-typed languages: one of 
them in line with the aformentioned, the other taking over the semantic 
and runtime as well. There are also two terms: "optional typing" and 
"gradual typing". I really don't know if those are defined precisely, 
but there seemed to be a sentiment that "optional typing" is the 
Gilad-Brachaish Strongtalk-like view, and "gradual typing" is the view 
that actually changes the semantics of the language and the runtime. 
What I wanted to say, is, that maybe this thread should be called "ES8 
Proposal: Gradual Static Typing".

And I forgot the second one. Though I personally think changing the 
semantics (do gradual typing) would change the language to something 
very different and may complicate the good old duck-typing way of doing 
things. Truly optional typing, in the sense of "help the tools and 
document" is good, though. But it is completely different debate (some 
foods for though: 1. We have JSDoc which already does that - we can 
type-annotate and tools do the work; 2. An eye-opener is to learn that 
there is distinction between nominal types and structural types. Does it 
not suit ES, as a duck-typing language, to have optional structural 
typing instead of optional nominal typing?).

Herby


Brandon Andrews wrote:
> ES8 Proposal: Optional Static Typing
>
> It was once said by Brendan Eich that 'Types are hard. This doesn't mean "no, never".' It's been a while since ES4. With ES6's TypedArrays and classes finalized and ES7 SIMD getting experimental tests, ECMAScript is in a good place to finally discuss types again. The demand for types as a different approach to code has been so strong in the past few years that separate languages have been created to deal with the perceived shortcomings. Types won't be an easy discussion, nor an easy addition, since they touch a large amount of the language; however, they are something that needs rigorous discussion. I'm hoping this initial proposal can be a way of pushing the ball forward. Turning this into an official proposal discussed by TC39 is the goal. This could very well be most of ES8 due to the complexity.
>
> Since it would be potentially years before this would be implemented this proposal includes a new keyword "enum" for enumerated types and the following types:
>
> number
> bool
> string
> object
> int8/16/32/64
> uint8/16/32/64
> bignum
> float16/32/64/80/128
> decimal32/64/128
> int8x16/16x8/32x4/64x2/8x32/16x16/32x8/64x4
> uint8x16/16x8/32x4/64x2/8x32/16x16/32x8/64x4
> float32x4/64x2/32x8/64x4
> rational
> complex
> any
> void
>
> These types bring ECMAScript in line or surpasses the type systems in most languages. For developers it cleans up a lot of the syntax, as described later, for TypedArrays, SIMD, and working with number types (floats vs signed and unsigned integers). It also allows for new language features like function overloading and a clean syntax for operator overloading. For implementors, added types offer a way to better optimize the JIT when specific types are used. For languages built on top of Javascript this allows more explicit type usage and closer matching to hardware.
>
> In theory the following current keywords could be deprecated in the long-term: Boolean, Number, String, Object, and the TypedArray objects. Their methods and features would be rolled into the new type system.
>
> One of the first complications with types is typeof's behavior. All of the above types would return their string conversion including bool. (In my experience "boolean" is seen as verbose among C++ and C# developers. Breaking this part of Java's influence probably wouldn't hurt to preserve consistency for the future).
>
> The next few parts cover type features that should be supported. The examples aren't meant to be exhaustive but rather show parts of the language that require new grammar and discussion.
>
> Support for nullable types.
>
> var foo:uint8? = null;
>
> Support for resizable typed arrays.
>
> var foo:uint8[];
> foo.push(1);
> var bar:uint8[] = [1, 2, 3, 4];
>
> Support for fixed-length typed arrays:
>
> var foo:uint8[4];
> foo.push(0); // invalid
> foo.pop(); // invalid
> var bar:uint8[4] = [1, 2, 3, 4];
>
> The ability to type any variable including arrow functions.
>
> var foo:uint8 = 0;
> var foo = uint8(0); // Cast
>
> var foo:(int32, string):string; // hold a reference to a signature of this type
> var foo = (s:string, x:int32) =>  s + x; // implicit return type of string
> var foo = (x:uint8, y:uint8):uint16 =>  x + y; // explicit return type
>
> Function signatures with constraints.
>
> function Foo(a:int32, b:string, c:bignum[], callback:(bool, string) = (b, s = 'none') =>  b ? s : ''):int32 { }
>
> Simplified binary shifts for integers:
>
> var a:int8 = -128;
> a>>  1; // -64, sign extension
> var b:uint8 = 128;
> b>>  1; // 64, no sign extension as would be expected with an unsigned type
>
> Destructing assignment casting:
>
> [a:uint32, b:float32] = Foo();
>
> Function overloading:
>
> function Foo(x:int32[]) { return "int32"; }
> function Foo(s:string[]) { return "string"; }
> Foo(["test"]); // "string"
>
> Constructor overloading:
>
> // 4 byte object
> value class MyType
> {
>      x:float32; // Able to define members outside of the constructor
>      constructor(x:float32)
>      {
>          this.x = x;
>      }
>      constructor(y:uint32)
>      {
>          this.x = float32(y) * 2;
>      }
> }
>
> Number would convert implicitly with precedence given to decimal, float128/80/64/32/16, uint64/32/16/8, int64/32/16/8. (Or whichever order makes the most sense). As an example using the MyType class:
>
> var t:MyType = 1; // float32 constructor call
> var t:MyType = uint32(1); // uint32 constructor called
>
> Implicit constructors could also be added to the proposed SIMD classes to go from a scalar to a vector.
>
> var v:float32x4 = 1; // Equivalent to an ES7 SIMD splat, so var v = float32x4(1, 1, 1, 1);
>
> Implicit array conversion would also exist:
>
> var t:MyType[] = [1, 2, 3, uint32(1)];
>
> Types would function exactly like you'd expect with decorators in ES7, but with the addition that they can be overloaded:
>
> function AlwaysReturnValue(value:uint32)
> {
>      return function (target, name, descriptor)
>      {
>          descriptor.get = () =>  value;
>          return descriptor;
>      }
> }
> function AlwaysReturnValue(value:float32) { /* ... */ }
>
> Class example and operator overloading:
>
> class Vector2d
> {
>      x: float32;
>      y: float32;
>      constructor(x:float32 = 0, y:float32 = 0)
>      {
>          this.x = x;
>          this.y = y;
>      }
>      Length():float32
>      {
>          return Math.sqrt(x * x + y * y); // uses Math.sqrt(v:float32):float32 due to input and return type
>      }
>      get X():float64 // return implicit cast
>      {
>          return this.x;
>      }
>      set X(x:float64)
>      {
>          this.x = x / 2;
>      }
>      operator +(v:vector2d)
>      {
>          return new vector2d(this.x + v.x, this.y + v.y);
>      }
>      operator ==(v:vector2d)
>      {
>          // equality check between this and v
>      }
> }
>
> Partial class in MyClass.js defining extensions to Vector2d:
>
> class Vector2d
> {
>      operator ==(v:MyClass)
>      {
>          // equality check between this and MyClass
>      }
>      operator +(v:MyClass)
>      {
>          return v + this; // defined in terms of the MyClass operator
>      }
> }
>
> Enumerations with enum that support any type except function signatures.
>
> enum Count { Zero, One, Two }; // Starts at 0
> var c:Count = Count.Zero;
>
> enum Count { One = 1, Two, Three }; // Two is 2 since these are sequential
> var c:Count = Count.One;
>
> enum Count:float32 { Zero, One, Two };
>
> Custom sequential function (these aren't closures):
>
> enum Count:float32 { Zero = (index, name) =>  index * 100, One, Two }; // 0, 100, 200
> enum Count:string { Zero = (index, name) =>  name, One, Two = (index, name) =>  name.toLowerCase(), Three }; // "Zero", "One", "two", "three"
>
> Index operator:
>
> enum Count { Zero, One, Two };
> Count[0];
>
> Get enum value as string:
>
> // Not sure what the syntax for this would be.
>
> Generic functions:
>
> function Foo<T>(foo:T):T
> {
>      var bar:T;
> }
>
> Generic classes:
>
> class Vector2d<T>
> {
>      x: T;
>      y: T;
>      constructor(x:T = 0, y:T = 0) // T could be inferred, but that might be asking too much. In any case T must have a constructor supporting a parameter 0 if this is a class.
>      {
>          this.x = x;
>          this.y = y;
>      }
> }
>
> Generic constraints aren't defined here but would need to be. TypeScript has their extends type syntax. Being able to constrain T to an interface seems like an obvious requirement. Also being able to constrain to a list of specific types or specifically to numeric, floating point, or integer types. Another consideration is being able to support a default type. Also generic specialization for specific types that require custom definitions. There's probably more to consider, but those are the big ideas for generics.
>
> Typedefs or aliases for types are a requirement. Not sure what the best syntax is for proposing these. There's a lot of ways to approach them. TypeScript has a system, but I haven't see alternatives so it's hard for me to judge if it's the best or most ideal syntax.
>
> Undecided Topics:
>
> I left value type classes out of this discussion since I'm still not sure how they'll be proposed. Doesn't sound like they have a strong proposal still or syntax.
>
> Unions are another topic not covered mostly because the syntax is very subjective. Without an added keyword the following might work in the grammar. The example uses an anonymous group unioned with an array of 3 elements. Using a class with x, y, and z members would also work. (Or using an interface syntax if one is added could work).
>
> class Vector3d
> {
>      {
>          {
>              x: float32;
>              y: float32;
>              z: float32;
>          }
>          a: float32[3];
>      }
> }
>
> Another example would be:
>
> class Color
> {
>      {
>          {
>              Red: float32;
>              Green: float32;
>              Blue: float32;
>              Alpha: float32;
>          }
>          Vector: float32x4;
>      }
> }
>
> The last topic not covered is if there should be new syntax for TypedArray views.
>
> var a1:uint32[] = [2, 0, 1, 3];
> var a2:uint64[] = a1(1, 2); // Creates a view of a1 at offset 1 with 2 elements. So [0, 1].
>
> That might be asking too much though. In a very compact form:
>
> var foo = ((uint64[])a1(1, 2))[0]; // foo would be 1
>
> This has been brought up before, but possible solutions due to compatability issues would be to introduce "use types"; or since ES6 has them Brenden once suggested something like:
>
>> import {int8, int16, int32, int64} from "@valueobjects";
>
> This concludes my proposal on types and the many facets of the language that would be potentially touched. The goal is essentially to turn this, or something similar, into a rough draft. Essentially build a foundation to start from expanding on edge cases and changes required in each part of the language. I'm sure with enough minds looking at each section this could be very well defined by the time ES8 is being considered.
>
> Previous discussions:
> This one contains a lot of my old thoughts (at least the stuff from 8 months ago). https://esdiscuss.org/topic/proposal-for-new-floating-point-and-integer-data-types
> https://esdiscuss.org/topic/optional-strong-typing
>
> https://esdiscuss.org/topic/optional-argument-types
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss


More information about the es-discuss mailing list