# Primitives

## string

### keywords

The following keywords can be referenced in any definition, e.g.:

```ts
const Email = type("string.email")

const User = type({
	data: "string.json.parse",
	ids: "string.uuid.v4[]"
})
```

| Alias | Description |
| --- | --- |
| `string` | a string |
| `string.alpha` | only letters |
| `string.alphanumeric` | only letters and digits 0-9 |
| `string.base58` | base58-encoded |
| `string.base64` | base64-encoded |
| `string.base64.url` | base64url-encoded |
| `string.capitalize` | a morph from a string to capitalized |
| `string.capitalize.preformatted` | capitalized |
| `string.creditCard` | a credit card number and a credit card number |
| `string.date` | a string and a parsable date |
| `string.date.epoch` | an integer string representing a safe Unix timestamp |
| `string.date.epoch.parse` | a morph from an integer string representing a safe Unix timestamp to a Date |
| `string.date.iso` | an ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) date |
| `string.date.iso.parse` | a morph from an ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) date to a Date |
| `string.date.parse` | a morph from a string and a parsable date to a Date |
| `string.digits` | only digits 0-9 |
| `string.email` | an email address |
| `string.hex` | hex characters only |
| `string.integer` | a well-formed integer string |
| `string.integer.parse` | a morph from a well-formed integer string to an integer |
| `string.ip` | an IP address |
| `string.ip.v4` | an IPv4 address |
| `string.ip.v6` | an IPv6 address |
| `string.json` | a JSON string |
| `string.json.parse` | safe JSON string parser |
| `string.lower` | a morph from a string to only lowercase letters |
| `string.lower.preformatted` | only lowercase letters |
| `string.normalize` | a morph from a string to NFC-normalized unicode |
| `string.normalize.NFC` | a morph from a string to NFC-normalized unicode |
| `string.normalize.NFC.preformatted` | NFC-normalized unicode |
| `string.normalize.NFD` | a morph from a string to NFD-normalized unicode |
| `string.normalize.NFD.preformatted` | NFD-normalized unicode |
| `string.normalize.NFKC` | a morph from a string to NFKC-normalized unicode |
| `string.normalize.NFKC.preformatted` | NFKC-normalized unicode |
| `string.normalize.NFKD` | a morph from a string to NFKD-normalized unicode |
| `string.normalize.NFKD.preformatted` | NFKD-normalized unicode |
| `string.numeric` | a well-formed numeric string |
| `string.numeric.parse` | a morph from a well-formed numeric string to a number |
| `string.regex` | a string and a regex pattern |
| `string.semver` | a semantic version (see https://semver.org/) |
| `string.trim` | a morph from a string to trimmed |
| `string.trim.preformatted` | trimmed |
| `string.upper` | a morph from a string to only uppercase letters |
| `string.upper.preformatted` | only uppercase letters |
| `string.url` | a string and a URL string |
| `string.url.parse` | a morph from a string and a URL string to a URL instance |
| `string.uuid` | a UUID |
| `string.uuid.v1` | a UUIDv1 |
| `string.uuid.v2` | a UUIDv2 |
| `string.uuid.v3` | a UUIDv3 |
| `string.uuid.v4` | a UUIDv4 |
| `string.uuid.v5` | a UUIDv5 |
| `string.uuid.v6` | a UUIDv6 |
| `string.uuid.v7` | a UUIDv7 |
| `string.uuid.v8` | a UUIDv8 |

### literals

```ts
const Literals = type({
	singleQuoted: "'typescript'",
	doubleQuoted: '"arktype"'
})
```

### patterns

Regex literals specify an unanchored regular expression that an input string must match.

They can either be string-embedded or refer directly to a `RegExp` instance.

```ts
const Literals = type({
	stringEmbedded: "/^a.*z$/",
	regexLiteral: /^a.*z$/
})
```

Regex literals now carry full type inference via [arkregex](https://arktype.io/docs/blog/arkregex):

```ts
const Hex = type("/^[0-9a-fA-F]+$/")
//    Type<string>

const Semver = type("/^(\\d+)\\.(\\d+)\\.(\\d+)$/")
//    Type<`${number}.${number}.${number}`>
```

#### e(x)ec mode

Prefix a regex literal with `x` to parse capture groups at runtime, fully typed:

```ts
const User = type({
	birthday: "x/^(?<month>\\d{2})-(?<day>\\d{2})-(?<year>\\d{4})$/"
})

const data = User.assert({ birthday: "05-21-1993" })

// fully type-safe
data.birthday.groups.month // "05"
data.birthday.groups.day // "21"
data.birthday.groups.year // "1993"
```

For the standalone package (no ArkType required), see the full [arkregex announcement](https://arktype.io/docs/blog/arkregex).

### lengths

Constrain a string with an inclusive or exclusive min or max length.

**string**

```ts
const Bounded = type({
	nonEmpty: "string > 0",
	atLeastLength3: "string.alphanumeric >= 3",
	lessThanLength10: "string < 10",
	atMostLength5: "string <= 5"
})
```

**fluent**

```ts
const Bounded = type({
	nonEmpty: type.string.moreThanLength(0),
	atLeastLength3: type.keywords.string.alphanumeric.atLeastLength(3),
	lessThanLength10: type.string.lessThanLength(10),
	atMostLength5: type.string.atMostLength(5)
})
```

Range expressions allow you to specify both a min and max length and use the same syntax for exclusivity.

**string**

```ts
const Range = type({
	nonEmptyAtMostLength10: "0 < string <= 10",
	integerStringWith2To5Digits: "2 <= string.integer < 6"
})
```

**fluent**

```ts
const Range = type({
	nonEmptyAtMostLength10: type.string.moreThanLength(0).atMostLength(10),
	integerStringWith2To5Digits: type.keywords.string.integer.root
		.atLeastLength(2)
		.lessThanLength(6)
})
```

## number

### keywords

The following keywords can be referenced in any definition, e.g.:

```ts
const User = type({
	createdAt: "number.epoch",
	age: "number.integer >= 0"
})
```

| Alias | Description |
| --- | --- |
| `number` | a number |
| `number.Infinity` | Infinity |
| `number.NaN` | NaN |
| `number.NegativeInfinity` | -Infinity |
| `number.epoch` | an integer representing a safe Unix timestamp |
| `number.integer` | an integer |
| `number.safe` | at least -9007199254740991 and at most 9007199254740991 |

### literals

```ts
const Literals = type({
	number: "1337"
})
```

### ranges

Constrain a number with an inclusive or exclusive min or max.

**string**

```ts
const Bounded = type({
	positive: "number > 0",
	atLeast3: "number.integer >= 3",
	lessThanPi: "number < 3.14159",
	atMost5: "number <= 5"
})
```

**fluent**

```ts
const Bounded = type({
	positive: type.number.moreThan(0),
	atLeast3: type.keywords.number.integer.atLeast(3),
	lessThanPi: type.number.lessThan(3.14159),
	atMost5: type.number.atMost(5)
})
```

Range expressions allow you to specify both a min and max and use the same syntax for exclusivity.

**string**

```ts
const Range = type({
	positiveAtMostE: "0 < number <= 2.71828",
	evenNumberAbsoluteValueLessThan50: "-50 < (number % 2) < 50"
})
```

**fluent**

```ts
const Range = type({
	positiveAtMostE: type.number.moreThan(0).atMost(2.71828),
	evenNumberAbsoluteValueLessThan50: type.number
		.divisibleBy(2)
		.moreThan(-50)
		.lessThan(50)
})
```

### divisors

Constrain a `number` to a multiple of the specified integer.

**string**

```ts
const Evens = type({
	key: "number % 2"
})
```

**fluent**

```ts
const Evens = type({
	key: type.number.divisibleBy(2)
})
```

## bigint

To allow any `bigint` value, use the `"bigint"` keyword.

**string**

```ts
const Bigints = type({
	foo: "bigint"
})
```

**fluent**

```ts
const Symbols = type({
	foo: type.bigint
})
```

### literals

To require an exact `bigint` value in your type, you can use add the suffix `n` to a string-embedded [number literal](https://arktype.io/docs/primitives#number-literals) to make it a `bigint`.

```ts
const Literals = type({
	bigint: "1337n"
})
```

You may also use a [unit expression](https://arktype.io/docs/expressions#unit) to define `bigint` literals.

## symbol

To allow any `symbol` value, use the `"symbol"` keyword.

**string**

```ts
const Symbols = type({
	key: "symbol"
})
```

**fluent**

```ts
const Symbols = type({
	key: type.symbol
})
```

To reference a specific symbol in your definition, use a [unit expression](https://arktype.io/docs/expressions#unit).

No special syntax is required to define symbolic properties like `{ [mySymbol]: "string" }`. For more information and examples of how to combine symbolic keys with other syntax like optionality, see [properties](https://arktype.io/docs/objects#properties).

## boolean

To allow `true` or `false`, use the `"boolean"` keyword.

**string**

```ts
const Booleans = type({
	key: "boolean"
})
```

**fluent**

```ts
const Booleans = type({
	key: type.boolean
})
```

### literals

To require a specific boolean value, use the corresponding literal.

**string**

```ts
const Booleans = type({
	a: "true",
	b: "false",
	// equivalent to the "boolean" keyword
	c: "true | false"
})
```

**fluent**

```ts
const Booleans = type({
	a: type.keywords.true,
	b: type.keywords.false,
	// equivalent to the "boolean" keyword
	c: type.keywords.true.or(type.keywords.false)
})
```

## null

The `"null"` keyword can be used to allow the exact value `null`, generally as part of a [union](https://arktype.io/docs/expressions#union).

**string**

```ts
const MyObj = type({
	foo: "number | null"
})
```

**fluent**

```ts
const MyObj = type({
	foo: type.number.or(type.null)
})
```

## undefined

The `"undefined"` keyword can be used to allow the exact value `undefined`, generally as part of a [union](https://arktype.io/docs/expressions#union).

**string**

```ts
const MyObj = type({
	requiredKey: "number | undefined",
	"optionalKey?": "number | undefined"
})
```

**fluent**

```ts
const MyObj = type({
	requiredKey: type.number.or(type.undefined),
	optionalKey: type.number.or(type.undefined).optional()
})
```

> **Allowing undefined as a value does not make the key optional!**
>
> In TypeScript, a required property that allows `undefined` must still be present for the type to be satisfied.
>
> The same is true in ArkType.
>
> <details>
> 	<summary>See an example</summary>
>
> ```ts
> const MyObj = type({
> 	key: "number | undefined"
> })
>
> // valid data
> const validResult = MyObj({ key: undefined })
>
> // Error: name must be a number or undefined (was missing)
> const errorResult = MyObj({})
> ```
>
> </details>
