Data types
DashaScript is a statically typed language. In general, the type system in DashaScript is similar to TypeScript's one, but it does not contain some of TS's elements (e. g. generics). Also, its syntax is slightly different.
Basic types
Table of built-in types:
Type name | Value range | Examples |
---|---|---|
string | string | “hello”, “123”, … |
number | double-precision 64-bit binary format IEEE 754 | 5.2, -21, … |
boolean | logical | true, false |
You can declare the variable's type with a colon after its name. Any variable must have initial value (except for variable with nullable types).
Types can also be inferred during initialization, so you don't need to set it manually (see examples below).
Declaration of variables in the context:
context { num: number = 0; str: string = "Hello"; // flag's type will be infered to be boolean flag = false; }
Declaration of local variables:
node some_node { do { var num: number = 0; // str's type will be infered to be string var str = "Hello"; var flag: boolean = false; } }
string
The string
type represents textual data.
Any string literal value in code must be surrounded by double quotes (e.g. "Any string value"
).
Arithmetic operators:
Operator | Description | Return type | Example |
---|---|---|---|
+ | concatenation of two strings | string | "aba" + "caba" // "abacaba" |
Assignment operators:
Operator | Description | Example |
---|---|---|
= | direct assignment | var s: string = "aba"; // s == "aba" , set s = "caba"; // s == "caba" |
+= | concatenation assignment | var s: string = "aba"; set s += "caba"; // s == "abacaba" |
Comparison operators:
Operator | Description | Return type | Example |
---|---|---|---|
== | check if two strings are equal | boolean | "aba" == "aba" // true |
!= | check if two strings are not equal | boolean | "aba" != "aba" // false |
string literal type
String literal type can be considered as special case of type string
. A variable of string literal type may have only one value. For example: var s: "abacaba" = "abacaba"
.
You may use string literals to create constant/unmodifiable variables or to limit possible values of a variable (using string literals and unions)
Apart from the aspect described above, string literals act like simple strings.
number
The number
type represents numeric data that can be expressed as a number. All basic arithmetic operations are supported.
Arithmetic operators:
Operator | Description | Return type | Example |
---|---|---|---|
+ | addition of two numbers | number | 11 + 4 // 15 |
- | subtraction of two numbers | number | 11 - 4 // 7 |
* | multiplication of two numbers | number | 11 * 4 // 44 |
/ | division of two numbers | number | 11 / 4 // 2.75 |
% | modulo (remainder) of two numbers | number | 11 % 4 // 2 |
Assignment operators:
Operator | Description | Example |
---|---|---|
= | direct assignment | var n: number = 11; // n == 11 set n = 4 // n == 4 |
+= | addition assignment | var n: number = 11; set n += 4; // n == 15 |
-= | subtraction assignment | var n: number = 11; set n -= 4; // n == 7 |
Comparison operators:
Operator | Description | Return type | Example |
---|---|---|---|
== | equal to | boolean | 6 == 4 // false |
!= | unequal to | boolean | 6 != 4 // true |
< | less than | boolean | 6 < 4 // false |
<= | less than or equal to | boolean | 6 <= 4 // false |
> | greater than | boolean | 6 > 4 // true |
>= | greater than or equal to | boolean | 6 >= 4 // true |
boolean
The boolean
represents logical data type: true/false.
Logical operators:
Operator | Synonym | Description | Return type | Example |
---|---|---|---|---|
|| | or | logical or | boolean | true || false == true |
&& | and | logical and | boolean | true and false == false |
! | --- | logical negation | boolean | !true == false |
Assignment operators:
Operator | Description | Example |
---|---|---|
= | direct assignment | var b: boolean = true; // b == true set b = false; // b == false |
Comparison operators:
Operator | Description | Return type | Example |
---|---|---|---|
== | equal to | boolean | true == true // true |
!= | unequal to | boolean | true != true // false |
Nullable types
Nullable types allow the value to be set to the special value null
instead of usual values of the data type.
A variable of nullable type may not have any initial value. In that case such a variable will have the value of null
.
Use ?
to declare type as nullable: var x: number?;
.
null-checking
Most operations that are supported for non-nullable types are not supported for nullable types. For example, we can't concatenate values of type string
and string?
since second one can be null. That is why null-checking when working with nullable variables.
To check variable does not equal to null
use the following syntax:
var checkIsNull: boolean = someVariable is not null;
And similarly when checking the variable has the value of null
:
if (someVariable is null) { ... }
After a value is checked to be equal to null
this information will be used later in corresponding context.
Example
context { someString: string?; } node some_node { do { if (someString is not null) { // someString is considered as not null in this block #sayText(someString); } } }
Derived data types
Union types
You can create custom type that allows the variable to have values of several previously defined types (union of types).
Union of types may be enclosed in angle brackets (may be not), the combined types are separated by a pipe:
context { status: <"none"|"done"> = "none"; numberOrString: <number|string> = 0; } node some_node { do { set status = "done"; set numberOrString = "hello"; } }
Array
To declare array use the type of the elements followed by []
: var arrayOfStrings: string[] = [];
.
To access element of an array use []
. The access result is a nullable value since provided index may occur to be out of array range.
Example
context { arrayOfStrings: string[] = ["str1", "str2"]; } node some_node { do { var element = arrayOfStrings[0]; if (element is not null) { // element is considered as string } } }
Object
Object declaration is enclosed in curly braces, the object fields are declared as name and type, separated by a colon, each field declaration ends with a semicolon:
context { // Declaration of an "person" object with field "name", field "age" and nullable field "phone". person: { name: string; age: number; phone: string?; role: <"student"|"professor">; } = { name: "Allen", age: 28, phone: null, role: "student" }; }
You can access field values of some object using the dot symbol:
node some_node { do { #sayText("Person '" + $person.name + "', " + $person.sex + ", " + #stringify($person.age) + " years old"); } }
Other types
unknown
A variable of this type may contain any value that can be obtained in DashaScript:
var u1: unknown = null; var u2: unknown = 1; var u3: unknown = "string"; var u4: unknown = {flag: false, value: "value"};
There are no supported operations for this type.
empty
Special type that does not contain any values.
It can be used to denote that external function or block does not return any usable value.
The instance of this type can't be constructed explicitly. There are no supported operations for this type.
User-defined types
You can declare a custom type using the type
keyword:
type MyType = { name: string; age: number; };
It is better to declare your types before context
section.
You may also create a special .dsl
file with type declarations and include it in other .dsl
files.
Example
type Role = <"student"|"professor">; type Person = { name: string; age: number; phone: string?; role: Role; }; context { persons: Person[] = [{name: "Bob", age: 20, role: "student"}]; } node some_node { do { var firstPerson: string? = $persons[0]; if (firstPerson is not null) { sayText("Hello, " + firstPerson.name + "! You are the first person."); } else { sayText("Array is empty.") } } }
Type compatibility
DashaScript uses structural typing rules, similar to TypeScript. In short, that means that a value of type A
can be assigned to a variable of type B
only if A
has all the properties of B
, and the types of all of those are compatible with the types of properties of B
. Here are several examples:
type A = { prop1: number; prop2: number; }; // A is assignable to B type B = { prop1: number; }; // A is not assignable to C1: types of prop1 are not compatible type C1 = { prop1: string; }; // A is not assignable to C2: property prop3 is missing in A type C2 = { prop3: number; };
Type casting
You can convert between types using the as
operator. It performs "deep" type checking, recursively checking of the properties of its operand. If successful, val as Type
returns val
converted to the type Type
. If not, it returns null
. Thus, the type of the expression val as Type
is Type?
.
These examples use types defined in the previous section:
var a = { prop1: 1, prop2: 2 }; var b = a as B; // equivalent to // var b: B? = { prop1: 1, prop2: 2 }; var c1 = a as C1; // equivalent to // var c1: C1? = null; // use the result after a null check if (b is not null) { // ... } // or use the optional access operators #log(b?.prop1);