CoreMedia Content Cloud v11 Upgrade Guide / Version 2110
Table Of ContentsWhile ActionScript and TypeScript have a notion of interfaces and even use the same keyword, the semantics are different.
In ActionScript, an interface must be implemented by a class explicitly. It can be checked at run-time whether
an object is an instance of a given interface, using the ActionScript built-in operator is
. This means
that an interface must have some run-time representation.
In TypeScript, a class "automatically" implements an interface when it defines the same member signatures
(duck typing). You can, however, use the keyword implements
to explicitly state
that your class intends to implement some interface. A TypeScript interface defines a so-called ambient
type, that is a type that is only relevant for the compiler / type checker, but not at runtime. Consequently,
there is no built-in way to do an instance-of check. To simulate this, you have to provide custom functions that
test a given object (type assertions).
When converting code from ActionScript to TypeScript, we wanted to keep the ActionScript interface semantics, so
we had to find some way to represent interfaces and the is
operator in TypeScript.
Since Jangaroo ActionScript is compiled to JavaScript using the Ext class system, there already is a solution at
run-time. Interfaces are represented as "empty" Ext classes, that is classes that have no members, but an identity.
When a class A implements an interface I, in Ext, the class corresponding to I is mixed into
A. The is
check is implemented by looking up the mixins
hierarchy of the object's class.
We use a similar approach in TypeScript. An interface is represented as a completely abstract class,
that is an abstract class that only has abstract members. At runtime, again, only an empty class with an identity
remains. When implementing an interface, this abstract class is implemented and mixed in.
TypeScript allows to "implement a class", because a class actually defines two entities: a value (the "class
object" that exists at runtime) and a type (only relevant for the compiler). If you use a class in an
implements
clause, only its type is used. The mixin aspect is represented in
TypeScript by calling the Jangaroo utility function mixin
, which is usually imported as a
named import,
so you'll see it simply as mixin(Clazz, Interface1, ..., InterfaceN)
after the class declaration.
Furthermore, in ActionScript interfaces, only methods may be declared. TypeScript allows to declare fields in interfaces, too. Note that a field and an accessor pair is considered two different things in both languages.
The following example illustrates the differences. Assume that accessor pair foo
was meant as a field
(which ActionScript cannot express in an interface), while bar
was intended to be implemented as an
accessor pair. The underscore prefix of _bar
is left out in TypeScript, as #
private
names do not clash with public names, anyway.
ActionScript | TypeScript |
---|---|
interface IFoo { function get foo(): String; function set foo(value: String): void; function get bar(): Number; function set bar(value: Number): void; function isAFoo(obj: *): Boolean; } public class Foo implements IFoo { private var _foo: String; private var _bar: Number; public function get foo(): String { return _foo; } public function set foo(value: String): void { _foo = value; } public function get bar(): Number { return _bar; } public function set bar(value: Number): void { _bar = value; } public function isAFoo(obj: *): Boolean { return obj is IFoo; } } |
abstract class IFoo { abstract foo: string; abstract get bar(): number; abstract set bar(value: number); abstract isAFoo(obj: any): boolean; } class Foo implements IFoo { foo: string; #bar: number; get bar(): number { return this.#bar; } set bar(value: number) { this.#bar = value; } isAFoo(obj: any): boolean { return is(obj, IFoo); } } mixin(Foo, IFoo); |
Table 7.2. Interfaces ActionScript-TypeScript example comparison
Note that is
and mixin
must be imported from Jangaroo Runtime as a named import, so they can be
used simply as is
and mixin
. See below for details about importing and exporting in
TypeScript.