> For the complete documentation index, see [llms.txt](https://dsheiko.gitbook.io/bycontract/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dsheiko.gitbook.io/bycontract/custom-types.md).

# Custom Types

Pretty much like with [JSDoc @typedef](https://jsdoc.app/tags-typedef.html) one can declare a custom type and use it as a contract.

#### Validating against a Union Type

Here we define a union type for values that can contain either numbers or strings that represent numbers.

```javascript
import { validate, typedef } from "bycontract";
typedef( "NumberLike", "number|string" );
validate( 10, "NumberLike" ); // OK
validate( null, "NumberLike" ); // ByContractError: expected number|string but got null
```

#### Validating against a Complex Type

This example defines a type `#Hero`that represents an object/namespace required to have properties `hasSuperhumanStrength` and `hasWaterbreathing` both of boolean type.

```javascript
import { validate, typedef } from "bycontract";
typedef( "#Hero", {
  hasSuperhumanStrength: "boolean",
  hasWaterbreathing: "boolean"
});
var superman = {
  hasSuperhumanStrength: true,
  hasWaterbreathing: false
};
validate( superman, "#Hero" ); // OK
```

> Custom type in the example above is prefixed with  **sharp (#)** to avoid interfering with global objects. It's not required though.

When any of properties violates the specified contract an exception thrown

```javascript
var superman = {
  hasSuperhumanStrength: 42,
  hasWaterbreathing: null
};
validate( superman, "#Hero" ); 
// ByContractError:  property #hasSuperhumanStrength expected boolean but got number
```

If value misses a property of the complex type an exception thrown

```javascript
var auqaman = {
  hasWaterbreathing: true
};
validate( superman, "#Hero" ); 
// ByContractError: missing required property #hasSuperhumanStrength
```

#### Custom Types and modifiers

Custom type is treated the same way as any other type in JSDoc

```javascript
typedef( "#Hero", {
  hasSuperhumanStrength: "boolean",
  hasWaterbreathing: "boolean"
});

validate( { foo: superman }, "Object.<string, #Hero>" );       
validate( "text", "string|#Hero" );
validate( [ superman ], "#Hero[]" );
validate( null, "?#Hero" );
validate( false, "#Hero=" );
```
