Type System Basics
This chapter covers the fundamental building blocks of TypeScript's and Auto's type systems — primitive types, arrays, annotations, unions, and the critical differences in how each language handles type safety.
The any Escape Hatch
TypeScript provides an any type that completely disables type checking for a value. It is an intentional escape hatch for incremental adoption, but it is also the single most dangerous feature in the language:
// TypeScript — the any escape hatch
let data: any = "hello";
data = 42; // no error
data.toUpperCase(); // no error at compile time, crashes at runtime
data.someRandomMethod(); // also no error — silently brokenOnce any enters your codebase, it propagates. Any value derived from an any expression also becomes any, quickly eroding type safety across entire modules.
TypeScript also offers unknown, a type-safe version of any. You cannot use an unknown value without first narrowing its type:
let input: unknown = "hello";
input.toUpperCase(); // ERROR — Object is of type 'unknown'
if (typeof input === "string") {
input.toUpperCase(); // OK — narrowed to string
}Auto has no any type — and no unknown either. Every value has a concrete, checked type. This is not a limitation; it is a design choice that eliminates an entire category of runtime errors at the source.
Primitive Types
TypeScript's primitive types are inherited directly from JavaScript:
// TypeScript — all numbers are float64
let count: number = 42;
let pi: number = 3.14159;
let name: string = "hello";
let flag: boolean = true;
let nothing: null = null;
let undef: undefined = undefined;
let sym: symbol = Symbol("id");
let big: bigint = 9007199254740991n;The JavaScript number type is always float64 — even integers. This leads to well-known precision problems:
// TypeScript
0.1 + 0.2; // 0.30000000000000004 — not 0.3!Auto provides cleaner, more explicit primitives:
Key differences in Auto's primitives:
intandf64are separate types. Integer arithmetic is exact — no floating-point surprises for whole numbers.nilunifiesnullandundefined. JavaScript's two "empty" values are collapsed into one, simplifying null handling.- No
symbolorbigintbuilt-in. Auto covers these use cases through its standard library when needed.
Arrays
Arrays are ordered, indexed collections of a single element type.
// TypeScript — array syntax
let numbers: number[] = [1, 2, 3];
let names: string[] = ["Alice", "Bob"];
let matrix: boolean[][] = [[true, false], [false, true]];
numbers.push(4);
const last = numbers.pop();
const len = numbers.length;
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);// Auto — array syntax
let numbers []int = [1, 2, 3]
let names []str = ["Alice", "Bob"]
let matrix [][]bool = [[true, false], [false, true]]
numbers.push(4)
let last = numbers.pop()
let len = numbers.len()
let doubled = numbers.map((n int) => n * 2)
let evens = numbers.filter((n int) => n % 2 == 0)Auto places the bracket before the type ([]int), following the convention of Go and Pascal. TypeScript places it after (number[]). The meaning is identical: a homogeneous list of values.
Type Annotations on Variables
TypeScript uses a colon to annotate a variable's type:
// TypeScript — explicit annotations
let age: number = 30;
let name: string = "Alice";
let active: boolean = true;
// TypeScript — type inference
let score = 100; // inferred as number
let greeting = "hi"; // inferred as stringAuto uses space-separated annotations — no colon:
// Auto — explicit annotations
let age int = 30
let name str = "Alice"
let active bool = true
// Auto — type inference
let score = 100 // inferred as int
let greeting = "hi" // inferred as strIn both languages, annotations are optional when the compiler can infer the type from the initializer. Use explicit annotations when the intent matters more than brevity — function parameters and public APIs are good candidates.
Interfaces as Types
TypeScript uses interface to define object shapes:
// TypeScript
interface Point {
x: number;
y: number;
}
let p: Point = { x: 1, y: 2 };Auto unifies type and interface into a single type declaration. This eliminates the common TypeScript confusion about when to use each:
// Auto
type Point {
x f64
y f64
}
let p Point = { x: 1, y: 2 }We will explore type declarations in depth in ch05.
Union and Intersection Types
Union types let a value be one of several types. Both TypeScript and Auto use the | operator:
// TypeScript
let id: string | number = 42;
id = "user-001"; // OK — both types are allowed// Auto
let id: int | str = 42
id = "user-001" // OKIntersection types combine multiple types into one. TypeScript uses &:
// TypeScript
interface HasId { id: number; }
interface HasName { name: string; }
type User = HasId & HasName;Auto does not have intersection types. Instead, it uses has composition to mix traits into types — a pattern we will cover in ch05 and ch12.
Nullable types are a special case of unions. In TypeScript you write string | null. Auto provides syntactic sugar:
// Auto — nullable sugar
let name ?str = nil // equivalent to str | nilThe ? prefix is concise and makes nullable types instantly recognizable in code.
Tuple Types
Tuples are fixed-length, positional arrays where each position has its own type.
// TypeScript — tuple
let pair: [string, number] = ["hello", 42];
let first: string = pair[0];
let second: number = pair[1];// Auto — tuple
let pair = ("hello", 42)
let first str = pair.0
let second int = pair.1Tuples are useful for returning multiple values from a function, but they should be used sparingly — a named type is almost always clearer.
Quick Reference
| Concept | TypeScript | Auto |
|---|---|---|
| Escape hatch | any, unknown | None — all types checked |
| Integer | number (float64) | int |
| Float | number (float64) | f64 |
| String | string | str |
| Boolean | boolean | bool |
| Null / Undefined | null, undefined | nil |
| Nullable | T | null | ?T |
| Array | number[] | []int |
| Annotation | let x: number | let x int |
| Object shape | interface / type | type |
| Union | string | number | str | int |
| Intersection | A & B | Use has composition |
| Tuple | [string, number] | (str, int) |