or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# ob1

1

2

ob1 is a small TypeScript library that provides type-safe operations for working with 0-based and 1-based numeric offsets using Flow's opaque types. It prevents common off-by-one errors by enforcing type distinctions at compile time while maintaining runtime efficiency through simple numeric operations.

3

4

## Package Information

5

6

- **Package Name**: ob1

7

- **Package Type**: npm

8

- **Language**: JavaScript with Flow types

9

- **Installation**: `npm install ob1`

10

11

## Core Imports

12

13

```javascript

14

const { add, sub, get0, get1, add1, sub1, neg, add0, inc } = require("ob1");

15

```

16

17

ES Modules:

18

```javascript

19

import { add, sub, get0, get1, add1, sub1, neg, add0, inc } from "ob1";

20

```

21

22

Flow Types:

23

```javascript

24

import type { Number0, Number1 } from "ob1";

25

```

26

27

## Basic Usage

28

29

```javascript

30

const { add0, add1, add, get0, get1 } = require("ob1");

31

32

// Create typed offsets

33

const zeroBasedIndex = add0(42); // Number0 type

34

const oneBasedLine = add1(41); // Number1 type (42 in 1-based)

35

36

// Type-safe arithmetic

37

const sum = add(zeroBasedIndex, 3); // Number0 + number = Number0

38

const mixed = add(zeroBasedIndex, oneBasedLine); // Number0 + Number1 = Number1

39

40

// Extract values

41

console.log(get0(sum)); // 45

42

console.log(get1(mixed)); // 85

43

```

44

45

## Architecture

46

47

ob1's architecture is built around Flow's opaque type system:

48

49

- **Opaque Types**: `Number0` and `Number1` are distinct numeric types that prevent accidental mixing

50

- **Type Safety**: Operations preserve offset semantics through overloaded function signatures

51

- **Runtime Efficiency**: All operations are simple numeric calculations with zero runtime overhead

52

- **Compile-time Validation**: Flow prevents unsafe operations like adding two 1-based offsets

53

54

## Capabilities

55

56

### Type System

57

58

Core opaque types for representing different offset bases.

59

60

```javascript { .api }

61

// 0-based offset type (for array indices, positions starting from 0)

62

export opaque type Number0 = number;

63

64

// 1-based offset type (for line numbers, columns starting from 1)

65

export opaque type Number1 = number;

66

```

67

68

### Arithmetic Operations

69

70

Type-safe addition and subtraction with automatic type propagation.

71

72

```javascript { .api }

73

/**

74

* Add two offsets or numbers with type-safe result types

75

* @param a - First operand (Number0, Number1, or number)

76

* @param b - Second operand (Number0, Number1, or number)

77

* @returns Result preserving appropriate offset type

78

*/

79

declare function add(a: Number1, b: number): Number1;

80

declare function add(a: number, b: Number1): Number1;

81

declare function add(a: Number0, b: number): Number0;

82

declare function add(a: number, b: Number0): Number0;

83

declare function add(a: Number1, b: Number0): Number1;

84

declare function add(a: Number0, b: Number1): Number1;

85

declare function add(a: Number0, b: Number0): Number0;

86

87

/**

88

* Subtract a number or 0-based offset from a 1/0-based offset

89

* @param a - Minuend (Number0, Number1, or number)

90

* @param b - Subtrahend (Number0, Number1, or number)

91

* @returns Result with appropriate offset type

92

*/

93

declare function sub(a: Number1, b: number): Number1;

94

declare function sub(a: Number0, b: number): Number0;

95

declare function sub(a: number, b: Number0): Number0;

96

declare function sub(a: Number0, b: number): Number0;

97

declare function sub(a: Number1, b: Number0): Number1;

98

declare function sub(a: Number0, b: Number0): Number0;

99

declare function sub(a: Number1, b: Number1): Number0;

100

```

101

102

**Usage Examples:**

103

104

```javascript

105

const { add0, add1, add, sub, get0, get1 } = require("ob1");

106

107

const index = add0(5); // Number0

108

const line = add1(10); // Number1

109

110

// Safe additions

111

const newIndex = add(index, 3); // Number0 + number = Number0

112

const newLine = add(line, index); // Number1 + Number0 = Number1

113

114

// Safe subtractions

115

const diff = sub(line, line); // Number1 - Number1 = Number0 (distance)

116

const prevIndex = sub(index, 2); // Number0 - number = Number0

117

118

console.log(get0(newIndex)); // 8

119

console.log(get1(newLine)); // 16

120

console.log(get0(diff)); // 0

121

```

122

123

### Type Casting and Extraction

124

125

Functions for creating offset types and extracting underlying values.

126

127

```javascript { .api }

128

/**

129

* Cast a number to a 0-based offset

130

* @param x - Number to cast

131

* @returns Number0 offset type

132

*/

133

function add0(x: number): Number0;

134

135

/**

136

* Get the underlying number of a 0-based offset, casting away the opaque type

137

* @param x - Number0 offset or null/undefined

138

* @returns Underlying number value or null/undefined

139

*/

140

declare function get0(x: Number0): number;

141

declare function get0(x: void | null): void | null;

142

143

/**

144

* Get the underlying number of a 1-based offset, casting away the opaque type

145

* @param x - Number1 offset or null/undefined

146

* @returns Underlying number value or null/undefined

147

*/

148

declare function get1(x: Number1): number;

149

declare function get1(x: void | null): void | null;

150

```

151

152

### Offset Conversion

153

154

Functions for converting between 0-based and 1-based offset types.

155

156

```javascript { .api }

157

/**

158

* Add 1 to a 0-based offset, converting it to 1-based

159

* @param x - Number0 offset or regular number

160

* @returns Number1 offset (input + 1)

161

*/

162

function add1(x: Number0 | number): Number1;

163

164

/**

165

* Subtract 1 from a 1-based offset, converting it to 0-based

166

* @param x - Number1 offset

167

* @returns Number0 offset (input - 1)

168

*/

169

function sub1(x: Number1): Number0;

170

```

171

172

**Usage Examples:**

173

174

```javascript

175

const { add0, add1, sub1, get0, get1 } = require("ob1");

176

177

// Array index to line number conversion

178

const arrayIndex = add0(4); // 5th element (0-based)

179

const lineNumber = add1(arrayIndex); // Line 5 (1-based)

180

181

// Line number to array index conversion

182

const currentLine = add1(42); // Line 43 (1-based)

183

const arrayPos = sub1(currentLine); // Index 42 (0-based)

184

185

console.log(get0(arrayIndex)); // 4

186

console.log(get1(lineNumber)); // 5

187

console.log(get0(arrayPos)); // 42

188

```

189

190

### Utility Operations

191

192

Additional operations for incrementing and negating offsets.

193

194

```javascript { .api }

195

/**

196

* Increment a 0-based or 1-based offset by 1

197

* @param a - Offset to increment (Number0 or Number1)

198

* @returns Same offset type incremented by 1

199

*/

200

declare function inc(a: Number0): Number0;

201

declare function inc(a: Number1): Number1;

202

203

/**

204

* Negate a 0-based offset

205

* @param x - Number0 offset to negate

206

* @returns Negated Number0 offset

207

*/

208

function neg(x: Number0): Number0;

209

```

210

211

**Usage Examples:**

212

213

```javascript

214

const { add0, add1, inc, neg, get0, get1 } = require("ob1");

215

216

const index = add0(5);

217

const line = add1(10);

218

219

// Increment operations preserve type

220

const nextIndex = inc(index); // Number0: 6

221

const nextLine = inc(line); // Number1: 11

222

223

// Negation (only for Number0)

224

const negative = neg(index); // Number0: -5

225

226

console.log(get0(nextIndex)); // 6

227

console.log(get1(nextLine)); // 11

228

console.log(get0(negative)); // -5

229

```

230

231

## Type Safety Features

232

233

### Allowed Operations

234

235

ob1's type system allows these safe combinations:

236

237

- `Number0 + Number0 = Number0` - Adding two 0-based offsets

238

- `Number0 + Number1 = Number1` - Adding 0-based to 1-based yields 1-based

239

- `Number1 + Number0 = Number1` - Adding 1-based to 0-based yields 1-based

240

- `Number1 - Number1 = Number0` - Distance between 1-based positions

241

- `Number0/Number1 + number` - Adding plain numbers preserves offset type

242

243

### Prevented Operations

244

245

Flow will prevent these unsafe operations at compile time:

246

247

- `Number1 + Number1` - Adding two 1-based offsets is mathematically meaningless

248

- `Number0 - Number1` - Would create negative 0-based offsets

249

- `get0(Number1)` - Cross-type extraction

250

- `get1(Number0)` - Cross-type extraction

251

- `add1(Number1)` - Converting already 1-based offset

252

- `sub1(Number0)` - Converting already 0-based offset

253

- Direct arithmetic (`offset + 1`, `offset - 1`) - Must use provided functions

254

255

## Error Handling

256

257

ob1 operations are purely mathematical and do not throw exceptions. Invalid combinations are prevented at compile time through Flow's type system rather than runtime checks.

258

259

For null/undefined handling, the `get0` and `get1` functions have overloaded signatures that preserve null/undefined values:

260

261

```javascript

262

get0(null); // returns null

263

get0(undefined); // returns undefined

264

get1(null); // returns null

265

get1(undefined); // returns undefined

266

```