Type Checks

Blockly fully supports dynamic-typed models like JS and Python, and also includes support for static-typed models like C/C++ with a little extra work.

In either case, Blockly can prevent some non-sensical combinations from being constructed. The following three blocks have no business being connected to each other:

Each of Blockly's connection types (value inputs/outputs, next/previous statements) can be labeled with type information so that obviously invalid connections will refuse to connect. This gives users instantanous feedback and avoids many simple mistakes.

Value Inputs and Outputs

Let's start with a number block. When specifying the output a type string may also be set. Since this block is supposed to return a number, let's set the output type to the string 'Number':

JSON

{
  "type": "math_number",
  // ...
  "output": "Number",
}

JavaScript

Blockly.Blocks['math_number'] = {
  init: function() {
    // ...
    this.setOutput(true, 'Number');
  }
};

A more complex block is a math block that determines if a number is even. This block has an input that expects a number, and an output that returns a boolean. Here is the code that specifies this:

JSON

{
  "type": "math_number_property",
  // ...
  "args0": [
      // ...
      {
        "type": "input_value",
        "name": "NUMBER_TO_CHECK",
        "check": "Number"
      }
  ],
  "output": "Boolean"
}

JavaScript

Blockly.Blocks['math_number_property'] = {
  init: function() {
    // ...
    this.appendValueInput('NUMBER_TO_CHECK').setCheck('Number');
    this.setOutput(true, 'Boolean');
  }
};

When a number block is connected to this math block, both connections are of type 'Number', so the connection succeeds. Whereas if one attempted to plug a text block (with an output type of 'String') into the math block, then the two types would not match, and the connections would refuse to connect.

The "length of" block is similar, except it needs to be able to accept either a text block or a list block. Accordingly, instead of one string, its input's type is set to be an array of two options:

JSON

{
  "type": "text_length",
  // ...
  "args0": [
      // ...
      {
        "type": "input_value",
        "name": "VALUE",
        "check": ["String", "Array"]
      }
  ],
  "output": "Number"
}

JavaScript

Blockly.Blocks['text_length'] = {
  init: function() {
    // ...
    this.appendValueInput('VALUE').setCheck(['String', 'Array']);
    this.setOutput(true, 'Number');
  }
};

A block might conceivably return one of two or more types. Although there are no current examples of this in Blockly, this would be supported by setting the output type to be an array of types. If any single type in an input matches a type in an output, then the blocks may be connected.

Variables are an example of a value block that could hold any type. Thus their type can be set to null which represents a wildcard:

JSON

{
  "type": "variable_get",
  // ...
  "output": null
}

JavaScript

Blockly.Blocks['variable_get'] = {
  init: function() {
    // ...
    // Second parameter for type is optional, and null is the default.
    this.setOutput(true);
  }
};

This allows the block to be plugged into any input, regardless of the input's type(s).

Note that the type strings used in Blockly ('Number', 'Boolean', 'String', 'Array', 'Colour') are completely arbitrary. Any strings are acceptable, and new ones may be invented ad hoc. Just ensure consistency between the outputs and the inputs.

Statement Stacks

In the same way that the horizontal connections of inputs and outputs may be typed, the vertical statement stacks may also have type information. Most coding applications would not use this feature, since any statement can normally follow any other statement.

One rare example of typed statement connections may be seen in the Block Factory tab of the Blockly Developer Tools. Notice that field blocks may not be stacked where input blocks should go, and input blocks may not be stacked where field blocks should go.

There are three places where typed statements are defined: on the previous and next connections of a block, and on a statement input's connection. These define stacking notches on the top and bottom of a block that can only be connected to blocks whose notches are either untyped, or whose notches contain at least one matching type.

The following example demonstrates "Mouse" and "Rat" types, where either type of block can be added to a statement input RODENTS. However, this toy example does not support both mice and rats in the rodents list.

JSON

{
  "type": "append_mouse",
  "message0": "Mouse",
  "previousStatement": "Mouse",
  "nextStatement": "Mouse"
},

{
  "type": "rodent_list",
  "message0": "Rodents %1",
  "args0": [
      {
        "type": "input_statement",
        "name": "RODENTS",
        "check": ["Mouse", "Rat"]
      }
  ]
}

JavaScript

Blockly.Blocks['append_mouse'] = {
  init: function() {
    this.appendDummyInput().appendField('Mouse');
    this.setPreviousStatement(true, 'Mouse');
    this.setNextStatement(true, 'Mouse');
  }
};

Blockly.Blocks['rodent_list'] = {
  init: function() {
    this.appendDummyInput().appendField('Rodents');
    this.appendStatementInput('RODENTS')
        .setCheck(['Mouse', 'Rat']);
  }
};