I don’t think I’m proposing defeating types.

I’m suggesting we should have compile time type checking in cases where we’re 
forced to use untyped objects. This will *improve* type checking.

In cases where it’s practical to have strongly typed runtime instances, I’m all 
for the runtime improvements.

My $0.02,
Harbs

> On Jan 7, 2019, at 10:37 AM, Alex Harui <aha...@adobe.com.INVALID> wrote:
> 
> Some runtimes understand types.  We should not defeat that.  The runtime 
> optimization of types is usually better than untyped stuff.  JS in the 
> browser is an exception and may be only a temporary popular runtime in the 
> long term.
> 
> The pattern I proposed (createBlobPropertyBag) is a platform-independent 
> abstraction that allows SWF and future platform code  to actually generate a 
> type where the JS code could get away with a plain object.  But maybe we 
> should modify that proposal a bit so that the factory function takes optional 
> initialization parameters as well.
> 
> Type-safety has some development-time overhead.  That's why folks like AS 
> over Java.  You don't have to strongly-type everything.  Unfortunately, it 
> isn't our call that Google has decided to strongly type the init objects in 
> the browser.  Well, it is our call in that we can change the interfaces we 
> generate, but I'm not sure we should.  We want to have folks write code that 
> can work on other runtimes, and future runtimes are likely to understand 
> types.  Using plain objects might seem easy/fast now, but it is likely to be 
> a problem in the future.
> 
> I believe if we use this factory pattern, you should also never waste time 
> spell checking plain objects ever again.  The IDEs already know how to 
> code-hint an interface.  They don't know what to do when you type "{".  IOW, 
> if you type:
> 
>    new window.Event("foo", {
> 
> the current Royale  IDEs will not help you, but if you instead use the 
> proposed pattern:
> 
>    new window.Event("foo", createEventInit(
> 
> the IDE will offer the list of init properties.  And your code will work on 
> future runtime/platforms.
> 
> I think it would be a substantial change to the compiler to allow plain 
> objects where an interface is expected.  The parameters are checked in the 
> ABCReducer, even for JS output.  The midde-ground would be to say the 
> parameter is an Object and use metadata to tell the JS transpiler to check 
> the properties against an interface.  I don't think we check the 
> ArrayElementType metadata today, but we could someday if we don't fake 
> generics.  But again, that code has little chance of working on future 
> platforms without more layering underneath.
> 
> My 2 cents,
> -Alex
> 
> On 1/6/19, 11:37 PM, "Harbs" <harbs.li...@gmail.com 
> <mailto:harbs.li...@gmail.com>> wrote:
> 
>    There are three advantages to Typescript-style interfaces:
> 
>    1. There’s less typing and passing around objects is easier.
>    2. Plain objects are actually type checked. Instead of lying to the 
> compiler by using “as”, the compiler can check that the required properties 
> exist and are spelled correctly.
>    3. They completely disappear at runtime. “True” interfaces add bulk at 
> runtime needed for reflection and the like.
> 
>> Why would it be huge?
> 
>    From experience, the time spent casting and spellchecking plain objects is 
> very time consuming when you have a need for lots of plain objects. This 
> happens more often than you’d like in the “real world”…
> 
>    I’m envisioning two types of interfaces:
> 
>    1. Classic interfaces like we have now. This would offer runtime checking 
> and reflection. It would also offer type safety for future strongly typed 
> languages.
>    2. “Dynamic” or “Virtual” interfaces would offer type checking for dynamic 
> objects at compile-time only.
> 
>    I’m thinking of maybe decorating interfaces with [Dynamic] or [Virtual] to 
> tell the compiler that it’s a “fake” interface.
> 
>    Maybe we can support these kinds of interfaces in SWF output by simply 
> converting the type to “Object”. You wouldn’t get the runtime checking, but 
> you’d still get the compile-time checking.
> 
>    It might be possible to do something similar in Swift or Java, etc. too.
> 
>    Thoughts?
> 
>    Harbs
> 
>> On Jan 7, 2019, at 8:37 AM, Alex Harui <aha...@adobe.com.INVALID> wrote:
>> 
>> Feel free to make the changes.  I personally am trying to ensure type-safety 
>> instead of weaken it.  It is only this case where the cost is starting to 
>> outweigh the benefits.
>> 
>> Why would it be huge?  Why should we encourage the use of plain objects 
>> intead of classes?  It feels to JS-specific.  Future runtimes might have 
>> strict type-safety.
>> 
>> -Alex
>> 
>> On 1/6/19, 10:05 PM, "Harbs" <harbs.li...@gmail.com> wrote:
>> 
>>   Personally, I would like to have us support TypeScript-type interfaces 
>> where plain objects that have the correct properties pass the check.[1]
>> 
>>   I have no idea how difficult this would be for SWF-compatible code, but 
>> even if it’s supported for JS-only code, that would be a huge production 
>> booster. 
>> 
>>   My $0.02,
>>   Harbs
>> 
>>   
>> [1]https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.typescriptlang.org%2Fdocs%2Fhandbook%2Finterfaces.html&amp;data=02%7C01%7Caharui%40adobe.com%7C171969f4b3d545dd34f408d67472ed99%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636824434318742933&amp;sdata=sSZMOAaiWiux5KcvkOCQn3oYc4Xl1970UsFxSlCLNsw%3D&amp;reserved=0
>>  
>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.typescriptlang.org%2Fdocs%2Fhandbook%2Finterfaces.html&amp;data=02%7C01%7Caharui%40adobe.com%7C171969f4b3d545dd34f408d67472ed99%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636824434318742933&amp;sdata=sSZMOAaiWiux5KcvkOCQn3oYc4Xl1970UsFxSlCLNsw%3D&amp;reserved=0>
>>  
>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.typescriptlang.org%2Fdocs%2Fhandbook%2Finterfaces.html&amp;data=02%7C01%7Caharui%40adobe.com%7C171969f4b3d545dd34f408d67472ed99%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636824434318742933&amp;sdata=sSZMOAaiWiux5KcvkOCQn3oYc4Xl1970UsFxSlCLNsw%3D&amp;reserved=0
>>  
>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.typescriptlang.org%2Fdocs%2Fhandbook%2Finterfaces.html&amp;data=02%7C01%7Caharui%40adobe.com%7C171969f4b3d545dd34f408d67472ed99%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636824434318742933&amp;sdata=sSZMOAaiWiux5KcvkOCQn3oYc4Xl1970UsFxSlCLNsw%3D&amp;reserved=0>>
>> 
>>> On Jan 7, 2019, at 6:03 AM, Alex Harui <aha...@adobe.com.INVALID 
>>> <mailto:aha...@adobe.com.INVALID>> wrote:
>>> 
>>> I just fixed a bug in the compiler, and now we are getting more of these 
>>> implicit coercion errors because the recent Google Closure Typedefs now 
>>> specify interfaces as parameters to certain contructors (or maybe they 
>>> always did and the compiler is now getting better at catching these errors).
>>> 
>>> Code that looked like:
>>> 
>>>  var blob:Blob = new Blob([text], { type: 'text/plain' });
>>> 
>>> or
>>> 
>>>  customEvent = new window.Event(type, {bubbles: bubbles, cancelable: 
>>> cancelable});
>>> 
>>> now results in a compiler error because the plain objects don't implement 
>>> whatever interface of properties the constructor expects.  I think Google 
>>> Closure did this so that the properties in the plain object don't get 
>>> renamed by the minifier.
>>> 
>>> One solution, that Yishay tried in this commit was simply to lie to the 
>>> compiler and tell it that the plain object was a BlobPropertyBag.  And 
>>> while that is the "least amount of code" solution, I didn’t like that 
>>> solution because it looks funny to have lots of places in our code where a 
>>> plain object is coerced to a type.
>>> 
>>> So, I went and created classes that implement BlobPropertyBag and other 
>>> interfaces.  I didn't like adding the weight of additional class 
>>> definitions but the classes I did were small, just a couple of properties.  
>>> However, for Event,there is a pretty big list of properties just to specify 
>>> bubbles and cancelable.  The compiler was not catching that plain object 
>>> before, but now with the fix I just made it will.  And I’m not sure it is 
>>> worth adding a large class with lots of properties.
>>> 
>>> So, I thought of a third idea which is a hack between what Yishay tried and 
>>> the interface implementations I did, which is to have a factory that 
>>> returns an instance of the interface, but actually returns a plain object.  
>>> As long as no code actually tests that the instance implements the 
>>> interface, it should work.  And that would localize the coercion of a plain 
>>> object to an interface in relatively few known places in our code.
>>> 
>>> The pattern would be to create a top-level factory function() unless it 
>>> makes sense to add it to a class so for Blob it might look like:
>>> 
>>> /**
>>> * @royaleignorecoercion BlobPropertyBag
>>> */
>>> public function createBlobPropertyBag():BlobPropertyBag
>>> {
>>>  // return a plain object but fool the compiler into thinking it is an 
>>> implementation of the interface
>>>  return {} as BlobPropertyBag;
>>> }
>>> 
>>> IMO, this also future-proofs the code in case we ever run where there is 
>>> runtime type-checking and need to someday return a real concrete instance 
>>> that implements the interface.
>>> 
>>> Thoughts?
>>> -Alex
>>> 
>>> 
>>> On 12/26/18, 11:02 PM, "Yishay Weiss" <yishayj...@hotmail.com 
>>> <mailto:yishayj...@hotmail.com>> wrote:
>>> 
>>>  Sounds good, feel free to revert.
>>> 
>>> 
>>> 
>>>  ________________________________
>>>  From: Alex Harui <aha...@adobe.com.INVALID 
>>> <mailto:aha...@adobe.com.INVALID>>
>>>  Sent: Thursday, December 27, 2018 3:43:45 AM
>>>  To: dev@royale.apache.org <mailto:dev@royale.apache.org>; 
>>> comm...@royale.apache.org <mailto:comm...@royale.apache.org>
>>>  Subject: Re: [royale-asjs] branch develop updated: Fix implicit coercion 
>>> error
>>> 
>>>  I don't think we should hack it like this.  Casting a plain object to a 
>>> type makes the code look strange, and it might not minify correctly.  I 
>>> have a different fix I hope to put in shortly where we actually pass in an 
>>> instance of the BlogPropertyBag.
>>> 
>>>  -Alex
>>> 
>>>  On 12/26/18, 6:57 AM, "yish...@apache.org <mailto:yish...@apache.org>" 
>>> <yish...@apache.org <mailto:yish...@apache.org>> wrote:
>>> 
>>>      This is an automated email from the ASF dual-hosted git repository.
>>> 
>>>      yishayw pushed a commit to branch develop
>>>      in repository 
>>> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitbox.apache.org%2Frepos%2Fasf%2Froyale-asjs.git&amp;data=02%7C01%7Caharui%40adobe.com%7C171969f4b3d545dd34f408d67472ed99%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636824434318752951&amp;sdata=m9McisyKOiiy7%2B4fvcLTy965pevXn5RwKJ8C0b2T2EI%3D&amp;reserved=0
>>>  
>>> <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitbox.apache.org%2Frepos%2Fasf%2Froyale-asjs.git&amp;data=02%7C01%7Caharui%40adobe.com%7C171969f4b3d545dd34f408d67472ed99%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C636824434318752951&amp;sdata=m9McisyKOiiy7%2B4fvcLTy965pevXn5RwKJ8C0b2T2EI%3D&amp;reserved=0>
>>> 
>>> 
>>>      The following commit(s) were added to refs/heads/develop by this push:
>>>           new 2f127d4  Fix implicit coercion error
>>>      2f127d4 is described below
>>> 
>>>      commit 2f127d459ee807f197950e11af947c623c270369
>>>      Author: DESKTOP-RH4S838\Yishay <yishayj...@hotmail.com>
>>>      AuthorDate: Wed Dec 26 16:57:33 2018 +0200
>>> 
>>>          Fix implicit coercion error
>>>      ---
>>>       
>>> .../src/main/royale/org/apache/royale/storage/file/DataOutputStream.as  | 2 
>>> +-
>>>       .../apache/royale/storage/providers/AndroidExternalStorageProvider.as 
>>>   | 2 +-
>>>       .../royale/org/apache/royale/storage/providers/WebStorageProvider.as  
>>>   | 2 +-
>>>       3 files changed, 3 insertions(+), 3 deletions(-)
>>> 
>>>      diff --git 
>>> a/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/file/DataOutputStream.as
>>>  
>>> b/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/file/DataOutputStream.as
>>>      index cff76eb..55eab71 100644
>>>      --- 
>>> a/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/file/DataOutputStream.as
>>>      +++ 
>>> b/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/file/DataOutputStream.as
>>>      @@ -117,7 +117,7 @@ public class DataOutputStream extends 
>>> EventDispatcher implements IDataOutput
>>>           public function writeText(text:String):void
>>>           {
>>>                   COMPILE::JS {
>>>      -                   var blob:Blob = new Blob([text], { type: 
>>> 'text/plain' });
>>>      +                   var blob:Blob = new Blob([text], { type: 
>>> 'text/plain' } as BlobPropertyBag);
>>>                           _fileWriter.write(blob);
>>>                   }
>>>                   COMPILE::SWF {
>>>      diff --git 
>>> a/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/providers/AndroidExternalStorageProvider.as
>>>  
>>> b/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/providers/AndroidExternalStorageProvider.as
>>>      index ea79a5b..cf05a73 100644
>>>      --- 
>>> a/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/providers/AndroidExternalStorageProvider.as
>>>      +++ 
>>> b/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/providers/AndroidExternalStorageProvider.as
>>>      @@ -199,7 +199,7 @@ package org.apache.royale.storage.providers
>>>                                                                   
>>> _target.dispatchEvent(newEvent);
>>>                                                           };
>>> 
>>>      -                                                   var blob:Blob = 
>>> new Blob([text], { type: 'text/plain' });
>>>      +                                                   var blob:Blob = 
>>> new Blob([text], { type: 'text/plain' } as BlobPropertyBag);
>>>                                                           
>>> fileWriter.write(blob);
>>>                                                   }, function(e):void {
>>>                                                           var 
>>> errEvent:FileErrorEvent = new FileErrorEvent("ERROR");
>>>      diff --git 
>>> a/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/providers/WebStorageProvider.as
>>>  
>>> b/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/providers/WebStorageProvider.as
>>>      index 1632bfa..dd9c84c 100644
>>>      --- 
>>> a/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/providers/WebStorageProvider.as
>>>      +++ 
>>> b/frameworks/projects/Storage/src/main/royale/org/apache/royale/storage/providers/WebStorageProvider.as
>>>      @@ -199,7 +199,7 @@ package org.apache.royale.storage.providers
>>>                                                                   
>>> _target.dispatchEvent(newEvent);
>>>                                                           };
>>> 
>>>      -                                                   var blob:Blob = 
>>> new Blob([text], { type: 'text/plain' });
>>>      +                                                   var blob:Blob = 
>>> new Blob([text], { type: 'text/plain' } as BlobPropertyBag);
>>>                                                           
>>> fileWriter.write(blob);
>>>                                                   }, function(e):void {
>>>                                                           var 
>>> errEvent:FileErrorEvent = new FileErrorEvent("ERROR");

Reply via email to