README.md

jTypes provides developers with robust type management in JavaScript to improve the maintainability and scalability of web-based applications.
By utilizing familiar and proven design patterns from popular languages such as C++, C#, and Java, jTypes can simplify the development of web apps, libraries, and tools.
Since it is not a new language, jTypes doesn't require any transcompilation to messy and unmaintainable JavaScript like other web programming languages.
This makes it extremely simple and straightforward, especially for developers that are experienced with classical inheritance.
Using existing and upcoming language components that are implemented across all browsers and platforms, jTypes offers an efficient and effective framework for class-based object-oriented development that can quickly and easily adapt to the "quirks" of a constantly evolving web.

Requirements

jTypes requires ECMAScript 5, which is supported by any modern platform or browser. This includes the following desktop and mobile browser versions:

Internet Explorer 9

Firefox 4

Chrome 13

Safari 5.1

Opera 11.6

IE Mobile 9

Android 3

iOS Safari 5

Opera Mobile 11.5

Blackberry 7

IE Mobile 9 was released with the Windows Phone 7.5 update, also known as Mango; iOS 5 was released for the iPhone 3GS, iPhone 4, iPhone 4S, iPod Touch (3rd/4th gen), iPad, and iPad 2.

Setup

Include the core.js or core.min.js file in your application:

<scripttype="text/javascript"src="jtypes-2.2.3.min.js"></script>

Install the jTypes module in Node.js using npm:

npm install jtypes

Enabling ECMAScript 6 features with the --harmony flag is recommended for jTypes 2.2 when using preview release 0.11.0 or higher.

IntelliSense

The core.intellisense.js file can be included in Visual Studio 2012 to add support for IntelliSense with jTypes:

This file is also available in the .zip downloads on our website.

Classes

Classes help organize applications and libraries by promoting the reuse of code and facilitating the ease of maintainence. They are created by providing the jTypes compiler with a definitions object in the following format:

This definitions object is a template for creating instance objects. It provides initial primitive values for fields, and function references for methods and properties. These default field values must be primitives such as booleans, numbers, strings, or symbols; otherwise the compiler will use a default value of null. The following example compiles a class Color and defines the initial primitive values of three public fields:

If an instance of the Color class is instantiated, the fields will have their default primitive values. This is demonstrated by the assert() calls in the previous example. These fields can then be assigned any type of reference upon instantiation such as arrays, dates, functions, or objects.

The modifiers argument of the jTypes compiler accepts a space-separated string of keywords. However, if the final keyword in the modifiers string starts with a capital letter, it will be treated as a class name and be globally defined in the jTypes namespace.

Constraints

Type constraints restrict values to simplify the implementation and maintainence of classes. If a value is not of the respective type of the constraint, it is treated as a null reference instead:

array

Class

date

element (2.2.1)

error

function

jquery (2.2.1)

object

primitive

regexp

type

window

The type constraint object strictly checks for invalid values using a $$.type(...) that is equal to 'object', while primitive checks for invalid values using the $$.isPrimitive(...) method, and type checks for invalid values using the $$.isClass(...) method. The following example compiles a class Queue with the type constraint array on a protected field:

If the protected field is checked for a null reference in the dequeue() method, it is guaranteed to have a $$.type(...) equal to 'array' and can safely call the shift() method. If a class has its name defined in the modifiers string as in the previous example, it can also be used as a constraint:

Because the animations field is restricted using the type constraint, it is guaranteed to be of the type Queue and can safely call the dequeue() method.

Primitive Constraints

Primitive constraints use the primitive values false, 0, NaN, "", and Symbol() for default or invalid values instead of null references. Consequently, these values can be directly accessed without any reference checking because they always provide a primitive value that is neither undefined nor null:

boolean (bool)

integer (int)

number (float)

string

symbol

These constraints prevent values from being cross referenced because they implicitly convert wrapper objects such as new Number(...) to its primitive value. The following example compiles a struct Color using the type constraint int on the public fields:

Since the values '255' and null do not have a typeof that is equal to 'number', the fields green.red and green.blue are assigned the default value of 0. However, green.green is assigned a truncated value because 128.3 is a primitive number.

Struct Constraints

Struct constraints use default instances for default or invalid values instead of null references. These values can also be directly accessed without any reference checking because they always provide a default instance:

Struct

The following example compiles the class Element using the type constraint Color on the public fields:

The values of element.background and element.foreground in the previous example can be directly accessed without any reference checking because they always provide a Color struct.

Because default and invalid values of fields and automatically implemented properties are still internally stored as null references, default struct instances are not instantiated until the value is accessed.

Operators

Nullable Operator

The ? nullable operator defaults primitive constraints and structs to null references for invalid values. It can be postfixed to the following constraints:

boolean? (bool?)

integer? (int?)

number? (float?)

string?

Struct?

symbol?

This allows primitive constraints to comply with primitive data types that may not contain a value, and structs to replicate the behavior of models. The following example compiles an abstract class Shape with the ? operator postfixed to the type constraint Color:

Since the protected fields default to null values, any derived implementation of the Shape class must check their values for null references. The next example compiles a class Polygon with a non-primitive type constraint array on another protected field:

Because the inherited field this._stroke from the previous example is nullable, it must first be checked for a null reference before being concatenated in the toString() method, which is also the case with this._points and calling the join() method.

Not-Nullable Operator

The ! not-nullable operator prevents built-in constraints with default instances from using null references. Because primitive constraints only default to null values when the nullable operator is present, the not-nullable operator can be postfixed to the following non-primitive constraints:

array!

date!

error!

function!

jquery! (2.2.1)

Model!

object!

regexp!

This operator can be postfixed to models due to the fact that models do not call the constructor unless the new operator is present. The example below compiles a class Queue with the ! operator postfixed to the type constraint array:

Since the operator uses default instances for invalid values instead of null references, the dequeue() method in the previous example can safely call the shift() method without checking the protected field for a null reference.

Because default and invalid values of fields and automatically implemented properties are still internally stored as null references, default model instances are not instantiated until the value is accessed.

Coerce Operator

The ~ coerce operator performs implicit conversions for built-in types. It can be prefixed to the following constraints:

~array

~boolean (~bool)

~date

~integer (~int)

~number (~float)

~regexp

~string

This operator converts values using global casting methods such as $$.asArray(...) or $$.asString(...). It does not alter the default value of fields and automatically implemented properties for non-primitive constraints. The following example compiles a struct Color with the ~ operator prefixed to the int type constraints:

Since none of the values being assigned to the fields in the previous example are primitive numbers, the $$.asInt(...) casting method will be used to coerce the values. To alter the default value of fields and automatically implemented properties for non-primitive constraints, the ~ and ! operators can be prefixed and postfixed:

~array!

~date!

~regexp!

Suppress Operator

at-symbol => @date

suppresses errors when jTypes.strict = true

Strict Constraints

require jTypes.strict = true, throw errors when a value is set that does not match the type of the constraint or !== null (which cannot be applied to constraints with the coerce modifier)

Namespaces

Namespaces help organize applications and libraries by controlling the scope of classes. They are created by providing the jTypes compiler with a callback function in the following format:

The namespace modifier in the modifiers string is optional and can be provided for readability.

Since this callback is invoked in the context of the namespace, the struct can be instantiated using this.Color in the scope of the callback function. Other scopes can instantiate this struct using the fully qualified reference from the global namespace:

var white =newjTypes.System.Drawing.Color(255, 255, 255);

These scopes also allow base classes and type constraints to be resolved from either the current or parent namespaces without requiring a fully qualified name. In the next example, an abstract class Shape is compiled in the scope of the System.Drawing.Drawing2D namespace:

The type constraint Color on the fields of the Shape class can be resolved without using the fully qualified name because the struct is defined in a parent namespace. If a class Rectangle is compiled in the same namespace as outlined in the example below, it can also reference the Shape class without using the fully qualified name:

While the Rectangle class is compiled in a separate callback function with its own unique scope and dependencies, the Shape class can still be referenced because it is already defined in the System.Drawing.Drawing2D namespace.

Dependencies

If a base class or type constraint cannot be resolved from either the current or parent namespaces, a dependencies array can prevent the need to specify a namespace or fully qualified name. The following example compiles an abstract class Control in the System.Forms namespace using an array of dependency strings:

This array of dependency strings can contain two types of declarations; alias definitions and namespace includes. Alias definitions contain the = assignment operator, while namespace includes do not.

Includes

Namespace includes allow identifiers in a namespace to be resolved without having to specify the namespace. The example below includes the System.Drawing namespace in the scope of the callback function:

Because this alias is defined in the scope of the callback function, the type constraint Color on the automatically implemented properties can be resolved. The fully qualified name on the right side of the alias definition can also be Drawing.Color due to the fact that System.Forms is a child namespace of System.

Aliases cannot hide a class already defined in the current namespace.

When there are conflicting names, aliases can be referenced directly using the :: operator. The following example uses the namespace alias qualifier to directly reference an alias in the type constraints on the automatically implemented properties:

The right side of an alias definition must be a namespace to use it with the :: operator. The global:: namespace alias qualifier is reserved for the global namespace. This allows base classes and type constraints to be referenced using globally qualified names.

Class Modifiers

abstract

abstract classes: cannot be instantiated and can have abstract methods and properties

expando

expando classes: inject the __self object into the root of prototype chain of the instance matrix (and it is only available in legacy mode)

internal

internal classes: hide their type from the type() method on all instances and the __type accessor on the public instance (and non-internal classes cannot inherit from internal classes)

unlocked

Class Member Modifiers

abstract

abstract members: must be overridden in a derived class (and can only be used on methods or properties)

const

const members: are not [Writable] and can only be used with the prototype or static modifiers

hidden

hidden members: are not [Enumerable] (fields and properties are enumerable by default, methods are not)

new

new members: hide an inherited member (when not overriding)

override

override members: override an inherited abstract or virtual member

private

private members: are only accessible in the methods and properties of the class they are defined in

protected

protected members: are only accessible in the methods and properties of the class they are defined in and the methods and properties of any derived classes

prototype

prototype members: are defined on the prototype of the class constructor (Class.prototype)

public

public members: are accessible everywhere for the class they are defined in and any derived classes as well

readonly

readonly members: are only writable inside the constructor (and can only be used with fields and automatically implemented properties)

sealed

sealed members: cannot be overridden and must be used with the override modifier

static

static members: are defined on the class constructor (Class)

virtual

virtual members: can be overridden in a derived class (and can only be used on methods or properties)

visible

visible members: are [Enumerable] (methods are not enumerable by default, fields and properties are)

Global Settings

jT_FunctionLock

default: false

jT_Harmony

default: true

jT_Legacy

default: false

jT_PrototypeLock

default: false

jT_Shorthand

default: true

jT_Storage

default: false

jT_Writable

default: false

Performance

Futures

Generics

Interfaces

Events (Prioritized Queues)

DOM Event Binders

Dynamic Namespaces

Internal Methods and Accessors

Custom Constraint Handlers

Argument Type Constraints (Methods)

Factories

Indexers *

Partial Classes

Observable Classes *

Reflection (Introspection)

* Requires ECMAScript 6 Proxies

Precompiling (fusion Integration)

jTypes will soon provide support for precompiling static class definitions using our fusion language framework currently under development.
The lexer-parser utilities of fusion will be used to build an abstract syntax tree for each static class definition in a .jt file and transpile them into a .js file.
Any classes with inline strings, functions, and object literals will be transpiled into a jTypes class that requires no compiling at runtime.
This will provide developers with the ability to utilize dynamic runtime class definitions for rapid prototyping and precompiled static class definitions for efficiency.
It not only offers the best of both worlds, but allows your class definitions to be interchangeable between the two.