Hone

Lessons · TypeScript · Quick reference

TypeScript quick reference

146 topics, one line each, in the order Hone teaches them.

Hone is a place to practise programming. This sheet is the whole TypeScript track at a glance: every idea it covers, in the order they are taught, one line each. It is a map rather than a lesson. Read opens the full explanation of an idea; Practise gives you a question on it. Both are free, and reading needs no account at all.

Data structures and algorithms · Things in a line

linked listsA linked list is small objects, each holding a value and a reference to the next one, ending at null. There is no index and no length. Read: Objects that point at the next object · Practise linked lists
stacks and queuesAn array is already a stack: push and pop work at the end. For a queue, shift() takes from the front but moves every remaining item, so a real queue keeps a head index instead. Read: Last in first out, and first in first out · Practise stacks and queues
two pointersInstead of comparing every pair with two nested loops, put one index at each end and move them toward each other, deciding at each step which one to move. Read: Two fingers, one pass · Practise two pointers
the sliding windowKeep a start and an end over the same sequence. The end always moves forward; the start moves forward only when the window has broken a rule. Read: A window that grows and shrinks · Practise the sliding window

Data structures and algorithms · Things in a grid

grids (a list of lists)grid[row][col]. The outer array holds rows, so the first bracket picks a row and the second picks a cell in it. Read: A grid is an array of arrays · Practise grids (a list of lists)
loop inside a loopn items in the outer loop times n in the inner is n squared. 1,000 becomes a million. Read: A loop inside a loop multiplies · Practise loop inside a loop
scanning an array is slowWalk the array once and keep a single number about the past; that is often all you need. Read: One pass, one running fact · Practise scanning an array is slow

Data structures and algorithms · Things in a tree

binary treesA binary tree node holds a value and at most two children. In a binary SEARCH tree everything left is smaller and everything right is larger. Read: A node, a left and a right · Practise binary trees
walking a treeDepth-first goes all the way down one branch before the next, and recursion does it for free. Breadth-first goes level by level, and needs a queue. Read: Two ways to visit every node · Practise walking a tree
a function that calls itselfA function that calls itself on a smaller input, with a base case that stops it. Read: A problem defined by a smaller version of itself · Practise a function that calls itself

Data structures and algorithms · Things in an order

what sorting costssort() costs about n log n and is stable in modern JavaScript, so items that compare equal keep the order they had. By default it sorts as TEXT, so numbers need a comparator. Read: What sorting costs, and what it buys · Practise what sorting costs
heaps (the smallest first)A heap keeps only enough order to know its minimum, so push and pop each cost about log n. JavaScript has no heap in the standard library, so you write the two loops yourself. Read: Always hand me the smallest · Practise heaps (the smallest first)
sort with a comparatorThe comparator decides order: return negative, zero or positive. To sort by two fields, compare the first and fall through to the second. Read: Sort by the thing that matters · Practise sort with a comparator

Data structures and algorithms · Things joined to things

graphs (things joined to things)A graph is usually a Map, or a plain object, from each node to the list it joins. Unlike a tree it can hold cycles, so every walk needs a Set of what it has already seen. Read: Things joined to things · Practise graphs (things joined to things)
memoising (not doing it twice)When a recursion asks the same smaller question down more than one branch, store each answer the first time. The code barely changes; the cost changes class. Read: Remember what you already worked out · Practise memoising (not doing it twice)
greedy choicesA greedy algorithm makes the choice that looks best at each step and never reconsiders. That is why it is fast, and why it is sometimes wrong. Read: Take the best step now, and never look back · Practise greedy choices

TypeScript, properly · Why types

what TypeScript addsTypeScript adds types that are checked when you compile and erased when you run. The browser runs plain JavaScript; the mistakes were caught before it got there. Read: Types, checked before it runs · Practise what TypeScript adds
type annotationsname: type after a parameter or variable tells the compiler what it holds; the compiler then refuses anything else before the code runs. Read: Saying what a thing is · Practise type annotations
inferenceThe first assignment fixes a variable's type: let x = 3 makes x a number. A const gets the exact literal, so const y = 3 has type 3. Read: Types you did not write · Practise inference
types are gone at runtimeInterfaces and type annotations exist only for the compiler. After compiling, the browser runs plain JavaScript with no trace of them. Read: Types are gone at runtime · Practise types are gone at runtime
any turns the checking offA value typed any can do anything: any property, any call, no errors. It compiles, then crashes at runtime. unknown is the safe alternative. Read: any turns the checker off · Practise any turns the checking off

TypeScript, properly · Shapes

interfaces and optional fieldsinterface Name { field: type; other?: type } describes what an object must have; ? marks a field that may be missing. Read: The shape of an object · Practise interfaces and optional fields
a property that may not be therenick?: string means the property may be absent; its type is really string | undefined, and you must check it before using it. Read: A property that may be missing · Practise a property that may not be there
union typesstring | number means 'either'. Until you check which, you may only use what both have. Read: One of several types · Practise union types
a type of exact values'GET' | 'POST' is a union of string literal types: the value must be one of those exact strings. A typo is a compile error. Read: Exactly these strings · Practise a type of exact values
a fixed-length, fixed-type array[string, number] is a tuple: exactly two items, a string at position 0 and a number at position 1. Each position has its own type. Read: A fixed shape of array · Practise a fixed-length, fixed-type array

TypeScript, properly · Narrowing

narrowing with checkstypeof, instanceof, Array.isArray, === null and 'in' inside an if narrow a union to one branch's type. Read: Checks the compiler follows · Practise narrowing with checks
teaching the compiler what it isA function returning x is string is a type predicate: when it returns true, the compiler treats the argument as a string in that branch. Read: A check the compiler remembers · Practise teaching the compiler what it is
strict null checksWith strict null checks, null and undefined are their own types; a string cannot be null unless you say string | null. Read: Nothing has a type too · Practise strict null checks
unknown makes you check firstunknown accepts any value but allows no operation on it until you narrow it. It is any with the safety kept. Read: Anything in, nothing out until checked · Practise unknown makes you check first
null is not every type's memberWith strictNullChecks, a value typed string cannot hold null or undefined. Say string | null when it can, and the compiler makes you check before using it. Read: null is not a string · Practise null is not every type's member

TypeScript, properly · Generics and beyond

genericsfunction first<T>(xs: T[]): T uses a placeholder T that is filled in from the argument each call. Read: A function that keeps the type it was given · Practise generics
extends: what a generic must havefunction len<T extends { length: number }>(x: T) accepts any T that has a numeric length: strings and arrays yes, numbers no. Read: A generic with a requirement · Practise extends: what a generic must have
keyof: the names of the keyskeyof T is the union of T's property names as string literals: keyof { x: number; y: number } is 'x' | 'y'. Read: The keys as a type · Practise keyof: the names of the keys
discriminated unionsA union of objects that each have a literal 'kind' field. switch on kind and each case knows its fields. Read: A tag that tells the variants apart · Practise discriminated unions
never: proving you covered every caseIn a switch over a discriminated union, assigning the default case to a never variable makes adding a new variant a compile error until it is handled. Read: Every case, or a compile error · Practise never: proving you covered every case

TypeScript, properly · Classes and interfaces

typed fields and parameter propertiesIn TypeScript a class declares each field and its type before the constructor assigns it. A parameter property, constructor(public name: string), declares and assigns in one line. Read: Fields are declared with their types · Practise typed fields and parameter properties
private, protected, readonlyprivate members are reachable only inside the class body, protected also inside subclasses, and readonly ones can be assigned only where they are declared or in the constructor. Read: private, protected and readonly draw the fence · Practise private, protected, readonly
implements an interfaceclass Dog implements Animal promises that Dog has every member Animal declares, and the compiler checks it. Any object with the right shape satisfies Animal, whether it says implements or not. Read: An interface describes; a class implements and builds · Practise implements an interface
abstract classesabstract class Shape cannot be instantiated. It can carry real methods every subclass shares, and abstract members each subclass must supply. Read: An abstract class shares real code and demands the rest · Practise abstract classes
extends, override, instanceofA derived constructor calls super() before touching this. An overriding method keeps a compatible signature. instanceof narrows a base-typed variable to the subclass inside the if. Read: extends with super first, a compatible override, and instanceof narrowing · Practise extends, override, instanceof

TypeScript, properly · Prove it works

types promise, tests proveThe compiler checks that percent returns a number. Which number, for which input, is a claim only a test can make, and a claim that fails throws with your message. Read: Types promise a shape; a test proves a value · Practise types promise, tests prove
a typed testA test file is compiled like any other file, so a test that calls the code with the wrong shape fails at compile time, and a test that runs asserts one fact. Read: A typed test is checked before it runs · Practise a typed test
arrange, act, assert, typedSet up typed inputs, make the one call, check the result. The annotation on the fixture documents what the function expects and refuses a wrong one. Read: Arrange, act, assert, with the fixture typed · Practise arrange, act, assert, typed
the type names the edgeA return type of number | undefined or number | null admits the empty case out loud, forces every caller to handle it, and gives the test a case to prove. Read: The type names the edge; the test proves it · Practise the type names the edge

More

some() and every()arr.some(fn) asks 'is at least one true?', arr.every(fn) asks 'are they all true?', in one line. Read: Asking a question of every item at once · Practise some() and every()
storing a value in a nameconst name = value stores a value under a name so you can use it again; let is for names that will be reassigned. Read: Naming a value · Practise storing a value in a name
async always hands back a promiseMarking a function async wraps its return value in a Promise. return 1 becomes a promise that resolves to 1, and a throw becomes a rejected promise. Read: An async function always returns a promise · Practise async always hands back a promise
functions that rememberA function keeps access to the variables around it when it was created, even after the outer function has returned. Read: A function that remembers where it was made · Practise functions that remember
map and filtermap transforms each item; filter keeps some; chain them to do both, without a loop and a push. Read: Build a new array from an old one · Practise map and filter
reassigning a constconst means the variable cannot be pointed at something else; the object or array it points to can still change. Read: const fixes the name, not the contents · Practise reassigning a const
template literalsA template literal `...${value}...` drops a value into a string where the braces are. Read: Putting values into text · Practise template literals
look it up in a MapWalk the data once; store each thing you see in a Map (or object) keyed by what you will later need to look up. Read: Remember what you have seen, in a Map · Practise look it up in a Map
reading a name before it existsFunction declarations are hoisted whole, so you can call them above their definition. var is hoisted as undefined. let and const are hoisted but unusable before their line. Read: What exists before its line · Practise reading a name before it exists
is it in therearray.includes(x) and string.includes(sub) answer yes or no; indexOf gives the position or -1. Read: Is it in there? · Practise is it in there
Math.floor and %JavaScript has no integer division operator: use Math.floor(a / b) for the whole part and a % b for the remainder. Read: Whole parts and remainders in JavaScript · Practise Math.floor and %
adding two numbersWith two numbers, + adds. The surprises come only when one side is a string, and from floating point, as in every language. Read: Plain addition · Practise adding two numbers
arrange, act, assertSet up the inputs, call the one thing being tested, check the result. Three short steps in that order, so a test can be read at a glance. Read: Arrange, act, assert · Practise arrange, act, assert
the first item is item 0arr[i] is the item at position i, counting from 0. Out of range gives undefined, not an error. Read: Picking an item by position · Practise the first item is item 0
pusharr.push(x) adds x to the end of the array in place and returns the new length. unshift adds to the front. Read: Adding to the end · Practise push
arrow functions and thisAn arrow function has no this of its own; it uses the this of the code around it. A regular function gets its own this, set by how it is called. Read: Arrows keep the this they were born in · Practise arrow functions and this
assertnode's assert throws an AssertionError with your message when a claim fails and does nothing when it holds. It is a sentence about your code that the computer checks. Read: assert says what must be true · Practise assert
async / awaitawait inside an async function pauses that function until the promise settles. Everything outside it keeps running, which is the whole point. Read: await pauses only its own function · Practise async / await
classes and newA class describes what a kind of thing has and does. new Dog('Rex') builds one Dog and runs its constructor on it. Read: A class builds objects with new · Practise classes and new
joining two strings+ between strings joins them, and a non-string on either side is turned into text first. A template literal, `Total: ${x}`, does the same more readably. Read: Joining text · Practise joining two strings
default parametersfunction f(x = 5) uses 5 only when x is undefined: missing, or passed as undefined. null and 0 are real values and are kept. Read: A default when the argument is missing · Practise default parameters
!! makes a boolean!!x converts any value to true or false by negating twice. It is the same conversion as Boolean(x). Read: Forcing a boolean · Practise !! makes a boolean
edge cases firstMost bugs live at the edges: the empty array, the single item, all items equal, and the division that becomes 0 / 0. Test those first; the middle usually follows. Read: Test the ends first: nothing, one, everything the same · Practise edge cases first
why === and not ==== converts the two sides to a common type before comparing, by rules almost nobody remembers; === compares as they are. Read: Why === and not == · Practise why === and not ==
the event loopCode already running finishes first. Then queued promise callbacks run, then timers. setTimeout(fn, 0) means 'after the current work', not 'now'. Read: What runs when · Practise the event loop
extends and superclass Puppy extends Dog makes every Dog method work on a Puppy. super(...) runs the parent's constructor, and a method of the same name in the child overrides the parent's. Read: extends shares a parent; super reaches it · Practise extends and super
filterarr.filter(fn) returns a new array of the items for which fn returned something truthy. The original is untouched. Read: Keeping what passes · Practise filter
getters, static and #privateget area() computes a value that is read without parentheses. static square() belongs to the class itself, not to instances. #w is a field only the class body can touch. Read: Getters read like properties; static lives on the class · Practise getters, static and #private
join (pieces to text)arr.join(sep) makes one string with sep between the items. split does the reverse. Read: Gluing a list into text · Practise join (pieces to text)
length and the last item"hello".length is 5 and [1, 2, 3].length is 3. length counts items; the last index is length - 1. Read: How many · Practise length and the last item
! flips true and false! turns true into false and false into true. Applied to a non-boolean it first converts the value to a boolean, which is why !0 is true. Read: Flipping a condition · Practise ! flips true and false
null vs undefined vs emptyx != null is true for every value except null and undefined. if (x) also rejects 0, '' and false, which is usually not what you meant. Read: Does it have a value · Practise null vs undefined vs empty
?? only catches null and undefineda ?? b gives b only when a is null or undefined. a || b gives b for every falsy a, including a real 0 or ''. Read: A default only for missing · Practise ?? only catches null and undefined
catching a promiseA promise that rejects with nobody listening is an unhandled rejection: often silent, sometimes fatal. Attach .catch, or await inside try/catch. Read: Catching a rejection · Practise catching a promise
prototypes under the hoodMethods written in a class body live once, on Dog.prototype; each object holds only its own fields and finds methods by walking the prototype chain. Read: A class is a prototype with nicer syntax · Practise prototypes under the hood
... spread[...a] makes a new array with the same items; {...o} does the same for objects. The copy is one level deep: nested arrays and objects are shared. Read: Copying with three dots · Practise ... spread
+ with a string and a numberIf either side of + is a string, + joins: '5' + 1 is '51'. Every other arithmetic operator converts to numbers instead. Read: When + stops adding · Practise + with a string and a number
the one-line ifcondition ? whenTrue : whenFalse is an expression: it produces one of the two values, so it can sit inside an assignment or a template. Read: A one-line if that has a value · Practise the one-line if
a test functionA test runner such as Jest or Vitest collects every test('name', fn) call, runs each, and reports the names that failed. Each test pins one fact down. Read: A test is a named function that asserts one fact · Practise a test function
this in methodsInside a method, this is whatever the method was called on. Detach the method from its object and this is gone. Read: this is the object before the dot · Practise this in methods
typeoftypeof x returns a string naming the type: 'string', 'number', 'boolean', 'undefined', 'object', 'function'. Read: What kind of value is this · Practise typeof
let is bounded by its blocklet and const are limited to the block they are declared in. var leaks out of its block, and reading a let before its line throws. Read: Where a variable lives · Practise let is bounded by its block
array or Map?An array is for things in order, reached by position; an object or Map is for things with a name, reached by key. Read: Array or object? · Practise array or Map?
copy before you change itObjects and arrays are passed by reference: changing one inside a function changes the caller's copy too. Read: Changing what was handed to you · Practise copy before you change it
never set, or set to nothingundefined is the absence nobody chose: a variable never assigned, a missing property. null is an absence someone set on purpose. Read: Two kinds of nothing · Practise never set, or set to nothing
object keys are textWhatever you use as a key on a plain object becomes a string. Numbers work by accident; objects collapse to '[object Object]'. Read: Object keys are strings · Practise object keys are text
counting loopsfor (let i = 0; i < n; i++) counts from 0 up to but not including n. Read: Counting with a loop · Practise counting loops
folding a list into one valuereduce walks the array carrying an accumulator; each step returns the new accumulator. Start it with an initial value. Read: Fold a list into one value · Practise folding a list into one value
leave as soon as you knowreturn ends the function immediately; handle the simple cases first and the main path stays unindented. Read: Leave as soon as you know · Practise leave as soon as you know
Set removes duplicatesA Set holds each value once and answers has() instantly. Read: A collection that refuses duplicates · Practise Set removes duplicates
slice copies, splice changesslice(start, end) returns a copy of part of the array; splice(start, count) removes items from the array itself. Read: slice copies, splice cuts · Practise slice copies, splice changes
slice()slice(start, end) takes items from start up to but not including end; negative numbers count from the end. Read: A window onto an array or string · Practise slice()
sorting numbers as textWithout a comparator, sort converts everything to strings: [10, 9, 1] becomes [1, 10, 9]. Read: sort() sorts as text · Practise sorting numbers as text
searching sorted dataIn a sorted array look at the middle; the target is there, left, or right. Discard half each time. Read: Halve the search space each step · Practise searching sorted data
memory for speedPrecompute once into a table, then read from it, instead of recomputing in a loop. Read: Spend memory to save time · Practise memory for speed
cleaning and reshaping texttrim, toLowerCase, split, replace, startsWith return new strings; the original never changes. Read: Cleaning and reshaping text · Practise cleaning and reshaping text
what counts as trueOnly six values are falsy: false, 0, '', null, undefined and NaN. Everything else is truthy, including '0', 'false', [] and {}. Read: What counts as true · Practise what counts as true
any vs unknownany lets you do anything, silently. unknown lets you do nothing until you check what it is. Read: any switches checking off; unknown makes you prove it · Practise any vs unknown
typing a listQuestions on Hone; no lesson yet. Practise typing a list
assertions (as)Questions on Hone; no lesson yet. Practise assertions (as)
as: telling, not checkingQuestions on Hone; no lesson yet. Practise as: telling, not checking
as const freezes the typeQuestions on Hone; no lesson yet. Practise as const freezes the type
typing true and falseQuestions on Hone; no lesson yet. Practise typing true and false
a brand that makes two strings differQuestions on Hone; no lesson yet. Practise a brand that makes two strings differ
a type that picks a branchQuestions on Hone; no lesson yet. Practise a type that picks a branch
const on a type parameterQuestions on Hone; no lesson yet. Practise const on a type parameter
declaring an interface twiceQuestions on Hone; no lesson yet. Practise declaring an interface twice
a union told apart by one fieldQuestions on Hone; no lesson yet. Practise a union told apart by one field
a conditional type spreads over a unionQuestions on Hone; no lesson yet. Practise a conditional type spreads over a union
enumQuestions on Hone; no lesson yet. Practise enum
typing a function's shapeQuestions on Hone; no lesson yet. Practise typing a function's shape
an index signatureQuestions on Hone; no lesson yet. Practise an index signature
infer: pulling a type outQuestions on Hone; no lesson yet. Practise infer: pulling a type out
what let infersQuestions on Hone; no lesson yet. Practise what let infers
an interface that is callableQuestions on Hone; no lesson yet. Practise an interface that is callable
what interfaces do that aliases cannotQuestions on Hone; no lesson yet. Practise what interfaces do that aliases cannot
JSON.parse hands back anyQuestions on Hone; no lesson yet. Practise JSON.parse hands back any
a type of one exact valueQuestions on Hone; no lesson yet. Practise a type of one exact value
a mapped typeQuestions on Hone; no lesson yet. Practise a mapped type
never: the return of a throwQuestions on Hone; no lesson yet. Practise never: the return of a throw
never, not voidQuestions on Hone; no lesson yet. Practise never, not void
never vanishes from a unionQuestions on Hone; no lesson yet. Practise never vanishes from a union
the ! that silences nullQuestions on Hone; no lesson yet. Practise the ! that silences null
typing an object's fieldsQuestions on Hone; no lesson yet. Practise typing an object's fields
Omit<T, K>Questions on Hone; no lesson yet. Practise Omit<T, K>
an optional parameterQuestions on Hone; no lesson yet. Practise an optional parameter
two signatures, one bodyQuestions on Hone; no lesson yet. Practise two signatures, one body
typing a parameterQuestions on Hone; no lesson yet. Practise typing a parameter
Partial<T>Questions on Hone; no lesson yet. Practise Partial<T>
Pick<T, K>Questions on Hone; no lesson yet. Practise Pick<T, K>
readonlyreadonly on a property or readonly T[] on an array makes mutation a compile error. Read: Promise not to change it · Practise readonly
Record<K, V>Questions on Hone; no lesson yet. Practise Record<K, V>
typing a returnQuestions on Hone; no lesson yet. Practise typing a return
satisfiesvalue satisfies Type checks the value fits Type without widening its inferred type. Read: Check the shape, keep the detail · Practise satisfies
shape, not nameQuestions on Hone; no lesson yet. Practise shape, not name
a type built from a stringQuestions on Hone; no lesson yet. Practise a type built from a string
type vs interfaceQuestions on Hone; no lesson yet. Practise type vs interface
why Dog[] is not Animal[]Questions on Hone; no lesson yet. Practise why Dog[] is not Animal[]
void: nothing worth usingQuestions on Hone; no lesson yet. Practise void: nothing worth using
while loopswhile (condition) repeats as long as the condition holds; use it when you do not know how many times in advance. Read: Repeat until something changes · Practise while loops
zip (walk two lists)Loop by index and read both arrays at position i, or map one array using the index to reach into the other. Read: Walking two arrays together · Practise zip (walk two lists)