# Typings

ActiveJS is strictly typed, it does its best to infer and enforce as many typings as possible. \
However, where it can't infer a type, it uses generics so that you can pass a type.

For example, [Units](/activejs/fundamentals/units.md), [Systems](/activejs/fundamentals/systems.md), and [Action](/activejs/fundamentals/action.md) accept a type for their value.\
[Cluster](/activejs/fundamentals/cluster.md) doesn't need to be passed types, as it can infer the types from the provided members automatically.

## Units

[BoolUnit](/activejs/fundamentals/units/boolunit.md), [NumUnit](/activejs/fundamentals/units/numunit.md), and [StringUnit](/activejs/fundamentals/units/stringunit.md) don't accept a type because it's already implied as `boolean`, `number`, and `string`, respectively.

[ListUnit](/activejs/fundamentals/units/listunit.md)'s value already has an `array` type, but it can't know about the type of items that the array is going to contain. You can pass it at the time of instantiation.

```typescript
// a ListUnit whose value type would be string[]
const namesList = new ListUnit<string>();

namesList.push('Mr. Anderson'); // works
namesList.dispatch(['Trinity', 'Morpheus']) // works

namesList.push(737); // linting error, invalid value
namesList.dispatch([737]) // linting error, invalid value
```

[DictUnit](/activejs/fundamentals/units/dictunit.md)'s value already has an `object` literal type, but it doesn't know the type of key-value pairs it's going to hold. You can pass it at the time of instantiation.

```typescript
// a DictUnit whose value type would be {[key in 'a' | 'b' | 'c']: number}
const someDict = new DictUnit<{[key in 'a' | 'b' | 'c']: number}>();

someDict.set('a', 1993) // works
someDict.dispatch({a: 1, b: 2, c: 3}) // works

someDict.set('b', 'not a number') // linting error, invalid value
someDict.set('d', 1993) // linting error, invalid key
someDict.dispatch({a: 1, b: 2}) // linting error, property 'c' is missing
```

[GenericUnit](/activejs/fundamentals/units/dictunit.md)'s value has an `any` type, it allows all types of values and leaves the typings to the developer. You can pass it at the time of instantiation.

```typescript
// a GenericUnit whose value type would be string | number | boolean
const primitivesUnit = new GenericUnit<string | number | boolean>();

primitivesUnit.dispatch(42); // works
primitivesUnit.dispatch('HanuMan'); // works
primitivesUnit.dispatch(true); // works

primitivesUnit.dispatch(['you and I']) // linting error, invalid value
primitivesUnit.dispatch({youAreMine: true}) // linting error, invalid value
```

## Systems

[AsyncSystem](/activejs/fundamentals/systems/asyncsystem.md) doesn't have a value of its own, it derives value from its member Units, 3 of them are GenericUnits and 1 is BoolUnit. The three GenericUnits can be supplied types through AsyncSystem's generics.

```typescript
type UserQuery = number; // type for queryUnit's value
type UserData = string; // type for dataUnit's value
type UserError = {status: number, message: string}; // type for errorUnit's value

// pass the types to AsyncSystem
const userSystem = new AsyncSystem<UserQuery, UserData, UserError>();

userSystem.queryUnit.dispatch(666) // works
userSystem.dataUnit.dispatch('evil string') // works
userSystem.errorUnit.dispatch({status: 418, message: "I'm a teapot"}) // works

userSystem.queryUnit.dispatch('not a number') // linting error, invalid value
userSystem.dataUnit.dispatch(420) // linting error, invalid value
userSystem.errorUnit.dispatch("I'm a teapot") // linting error, invalid value
```

[Custom AsyncSystem](/activejs/fundamentals/systems/custom-asyncsystem.md) doesn't need to be passed types explicitly, since it doesn't create Units itself, they are provided externally, and it can infer the types from the provided Units.

## Action

[Action](/activejs/fundamentals/action.md) has `any` as its default value type, it can be restricted by passing a specific type through generics.

```typescript
// an Action that will allow strings
const heroAction = new Action<string>();

heroAction.dispatch('fight injustice') // works
heroAction.dispatch('defeat bullies') // works

heroAction.dispatch(['catch', 22]) // liniting error, invalid value
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.activejs.dev/activejs/guides/type-safety.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
