diff --git a/exercises/01.expressions-and-output/01.problem.hello-world/README.mdx b/exercises/01.expressions-and-output/01.problem.hello-world/README.mdx
index 4387aac..734eaae 100644
--- a/exercises/01.expressions-and-output/01.problem.hello-world/README.mdx
+++ b/exercises/01.expressions-and-output/01.problem.hello-world/README.mdx
@@ -9,8 +9,16 @@ is how you see the results of your code.
π¨ Open and complete the following tasks:
-1. Use `console.log()` to print the string `"Hello, World!"`
-2. Use `console.log()` to print your name as a string
+1. Use `console.log()` to print the exact string `"Hello, World!"` (capital H,
+ capital W, comma, and exclamation mark)
+2. Use `console.log()` to print your name as a string on a second line
+
+## Completion criteria
+
+When you run the program, the output should include:
+
+- A line containing `Hello, World!`
+- At least one more non-empty line (your name)
π° Strings are text values wrapped in quotes (single or double).
diff --git a/exercises/01.expressions-and-output/01.problem.hello-world/index.ts b/exercises/01.expressions-and-output/01.problem.hello-world/index.ts
index 0b265b5..57965e7 100644
--- a/exercises/01.expressions-and-output/01.problem.hello-world/index.ts
+++ b/exercises/01.expressions-and-output/01.problem.hello-world/index.ts
@@ -1,6 +1,6 @@
// Your First Program
// Let's print some messages to the console!
-// π¨ Use console.log() to print "Hello, World!"
+// π¨ Use console.log() to print the exact string "Hello, World!"
-// π¨ Use console.log() to print your name (as a string)
+// π¨ Use console.log() to print your name (as a string) on a second line
diff --git a/exercises/01.expressions-and-output/02.problem.escaping-strings/README.mdx b/exercises/01.expressions-and-output/02.problem.escaping-strings/README.mdx
index 6f0e7ac..0f008e5 100644
--- a/exercises/01.expressions-and-output/02.problem.escaping-strings/README.mdx
+++ b/exercises/01.expressions-and-output/02.problem.escaping-strings/README.mdx
@@ -41,12 +41,23 @@ console.log('Name:\tKody') // Prints with a tab between
π¨ Open and complete the following tasks:
-1. Log a string using single quotes that contains an apostrophe (like "It's
- working!")
-2. Log a string using double quotes that contains a quoted phrase (like: She
- said "Hi")
-3. Log "Hello" and "World" on separate lines using `\n` in a single string
-4. Log tab-separated column headers: "Name:" "Age:" "City:" using `\t`
+1. Log the exact string `It's working!` using a single-quoted string (escape the
+ apostrophe)
+2. Log the exact string `She said "Hi"` using a double-quoted string (escape the
+ inner quotes)
+3. In a single string, log `Hello` and `World` on separate lines (use a newline
+ escape)
+4. Log the exact tab-separated headers: `Name:` then tab then `Age:` then tab
+ then `City:`
+
+## Completion criteria
+
+Your program output should include all four of these (exact text and whitespace):
+
+- `It's working!`
+- `She said "Hi"`
+- `Hello` and `World` separated by a newline in one log
+- `Name:\tAge:\tCity:` (tabs between the labels)
π° Use backslash escape sequences for quotes, newlines, and tabs. The table
above is your reference.
diff --git a/exercises/01.expressions-and-output/02.problem.escaping-strings/index.ts b/exercises/01.expressions-and-output/02.problem.escaping-strings/index.ts
index 1553b6e..efd36e4 100644
--- a/exercises/01.expressions-and-output/02.problem.escaping-strings/index.ts
+++ b/exercises/01.expressions-and-output/02.problem.escaping-strings/index.ts
@@ -1,10 +1,10 @@
// Escaping Strings
// Learn to include special characters in strings
-// π¨ Log "It's working!" using single quotes (you'll need to escape the apostrophe)
+// π¨ Log exactly: It's working! (single-quoted string; escape the apostrophe)
-// π¨ Log: She said "Hi" (using double quotes for the string)
+// π¨ Log exactly: She said "Hi" (double-quoted string; escape the inner quotes)
-// π¨ Log "Hello" and "World" on separate lines using a single string with \n
+// π¨ Log "Hello" and "World" on separate lines using a single string with a newline escape
-// π¨ Log tab-separated data: Name: [tab] Age: [tab] City: (like column headers)
+// π¨ Log exactly: Name: [tab] Age: [tab] City:
diff --git a/exercises/01.expressions-and-output/03.problem.strings/README.mdx b/exercises/01.expressions-and-output/03.problem.strings/README.mdx
index 2418727..7ecb16c 100644
--- a/exercises/01.expressions-and-output/03.problem.strings/README.mdx
+++ b/exercises/01.expressions-and-output/03.problem.strings/README.mdx
@@ -14,10 +14,18 @@ console.log('Hello' + ' ' + 'World') // Prints: Hello World
π¨ Open and complete the following tasks:
-1. Log the result of concatenating `"Hello"` and `"TypeScript"` with a space
- between them
-2. Log your first name and last name concatenated together
-3. Log a longer message by concatenating multiple strings
+1. Concatenate the strings `"Hello"`, a space, and `"TypeScript"`, then log the
+ result (output must include `Hello TypeScript`)
+2. Concatenate your first name, a space, and your last name, then log the result
+3. Concatenate multiple small string pieces to produce exactly:
+ `I am learning to code` (include the spaces between words)
+
+## Completion criteria
+
+- Output includes `Hello TypeScript`
+- Output includes `I am learning to code`
+- Your source uses the `+` operator to concatenate string literals at least
+ three times (this step is about concatenation, not template literals)
π° Remember to include spaces where you need them - the `+` operator joins
strings exactly as they are!
diff --git a/exercises/01.expressions-and-output/03.problem.strings/index.ts b/exercises/01.expressions-and-output/03.problem.strings/index.ts
index 8f95cf4..4ab085b 100644
--- a/exercises/01.expressions-and-output/03.problem.strings/index.ts
+++ b/exercises/01.expressions-and-output/03.problem.strings/index.ts
@@ -1,9 +1,9 @@
// String Expressions
// Learn to work with text data
-// π¨ Log "Hello" + " " + "TypeScript" (concatenate these three strings)
+// π¨ Log the concatenation of "Hello", a space, and "TypeScript"
// π¨ Log your first name and last name concatenated together with a space
-// π¨ Log a sentence by concatenating multiple strings
+// π¨ Log the sentence "I am learning to code" by concatenating multiple strings
// π° Build the sentence from small pieces and include spaces where needed
diff --git a/exercises/01.expressions-and-output/03.solution.strings/index.test.ts b/exercises/01.expressions-and-output/03.solution.strings/index.test.ts
index 551b7d1..da02b23 100644
--- a/exercises/01.expressions-and-output/03.solution.strings/index.test.ts
+++ b/exercises/01.expressions-and-output/03.solution.strings/index.test.ts
@@ -27,7 +27,7 @@ const output = getOutput()
await test('should print Hello TypeScript', () => {
assert.ok(
output.includes('Hello TypeScript'),
- 'π¨ Output should include "Hello TypeScript" - concatenate "Hello" + " " + "TypeScript"',
+ 'π¨ Output should include "Hello TypeScript" - concatenate those three pieces with +',
)
})
diff --git a/exercises/01.expressions-and-output/04.problem.numbers/README.mdx b/exercises/01.expressions-and-output/04.problem.numbers/README.mdx
index 948ad42..b1f2738 100644
--- a/exercises/01.expressions-and-output/04.problem.numbers/README.mdx
+++ b/exercises/01.expressions-and-output/04.problem.numbers/README.mdx
@@ -25,10 +25,20 @@ a complete list in the
π¨ Open and complete the following tasks:
-1. Log the result of adding 25 and 17
-2. Log the result of multiplying 8 by 6
-3. Log the result of dividing 100 by 4
-4. Log the result of a more complex expression: `(10 + 5) * 2`
+1. Log the result of adding `25` and `17`
+2. Log the result of multiplying `8` by `6`
+3. Log the result of dividing `100` by `4`
+4. Log the result of adding `10` and `5`, then multiplying that sum by `2`
+ (group the addition so it happens first)
+
+## Completion criteria
+
+Your output should include these numeric results (each on its own line is fine):
+
+- `42` (from 25 + 17)
+- `48` (from 8 Γ 6)
+- `25` (from 100 Γ· 4)
+- `30` (from (10 + 5) Γ 2)
π° You can use parentheses to control the order of operations, just like in
regular math!
diff --git a/exercises/01.expressions-and-output/04.problem.numbers/index.ts b/exercises/01.expressions-and-output/04.problem.numbers/index.ts
index 1d7104f..4cde8be 100644
--- a/exercises/01.expressions-and-output/04.problem.numbers/index.ts
+++ b/exercises/01.expressions-and-output/04.problem.numbers/index.ts
@@ -7,5 +7,5 @@
// π¨ Use console.log to show the result of 100 divided by 4
-// π¨ Use console.log to show the result of (10 + 5) multiplied by 2
-// π° Use parentheses to control order of operations
+// π¨ Use console.log to show the result of adding 10 and 5, then multiplying by 2
+// π° Use parentheses so the addition happens before the multiplication
diff --git a/exercises/01.expressions-and-output/05.problem.template-literals/README.mdx b/exercises/01.expressions-and-output/05.problem.template-literals/README.mdx
index a1f6ecf..537a5bb 100644
--- a/exercises/01.expressions-and-output/05.problem.template-literals/README.mdx
+++ b/exercises/01.expressions-and-output/05.problem.template-literals/README.mdx
@@ -30,9 +30,22 @@ console.log(`Hello, ${'World'}!`) // Prints: Hello, World!
π¨ Open and complete the following tasks:
-1. Log a template literal that says "The answer is 42" using `${40 + 2}`
-2. Log a greeting that includes "Hello" and "TypeScript" in one template literal
-3. Log a math problem and its answer, like "10 times 5 equals 50"
+1. Log a template literal whose output is exactly `The answer is 42`, embedding a
+ calculation that evaluates to `42` (do not hardcode the digits `42` as plain
+ text alone)
+2. Log a greeting template literal that includes both `Hello` and `TypeScript`
+ (for example: `Hello, TypeScript!`)
+3. Log a math sentence whose output includes `50` as the computed answer (for
+ example: `10 times 5 equals 50`), embedding the multiplication in the
+ template
+
+## Completion criteria
+
+Your output should include:
+
+- `The answer is 42`
+- Text containing both `Hello` and `TypeScript` (any casing is fine for the check)
+- The number `50` as part of a logged math sentence
π° The backtick key is usually in the top-left of your keyboard, below Escape.
diff --git a/exercises/01.expressions-and-output/05.problem.template-literals/index.ts b/exercises/01.expressions-and-output/05.problem.template-literals/index.ts
index 464b275..80b0946 100644
--- a/exercises/01.expressions-and-output/05.problem.template-literals/index.ts
+++ b/exercises/01.expressions-and-output/05.problem.template-literals/index.ts
@@ -1,8 +1,9 @@
// Template Literals
// A better way to build strings
-// π¨ Log "The answer is 42" using a template literal with ${40 + 2}
+// π¨ Log "The answer is 42" using a template literal
+// π° Embed a calculation that evaluates to 42
-// π¨ Log "Hello, TypeScript!" using a template literal
+// π¨ Log a greeting that includes "Hello" and "TypeScript" using a template literal
-// π¨ Log a math problem like "10 times 5 equals 50"
+// π¨ Log a math sentence whose answer is 50 (embed the multiplication)
diff --git a/exercises/01.expressions-and-output/05.solution.template-literals/index.test.ts b/exercises/01.expressions-and-output/05.solution.template-literals/index.test.ts
index 7fcefb1..0baa3b0 100644
--- a/exercises/01.expressions-and-output/05.solution.template-literals/index.test.ts
+++ b/exercises/01.expressions-and-output/05.solution.template-literals/index.test.ts
@@ -26,7 +26,7 @@ const output = getOutput()
await test('should print "The answer is 42"', () => {
assert.ok(
output.includes('The answer is 42'),
- 'π¨ Output should include "The answer is 42" - use a template literal with ${40 + 2}',
+ 'π¨ Output should include "The answer is 42" - use a template literal and embed a calculation for 42',
)
})
@@ -41,6 +41,6 @@ await test('should print Hello, TypeScript! greeting', () => {
await test('should print math result with 50', () => {
assert.ok(
output.includes('50'),
- 'π¨ Output should include 50 (the result of 10 * 5) - use ${10 * 5} in a template literal',
+ 'π¨ Output should include 50 as the computed answer in a template-literal math sentence',
)
})
diff --git a/exercises/02.variables/01.problem.let-and-const/README.mdx b/exercises/02.variables/01.problem.let-and-const/README.mdx
index 07e3ae0..c81fa31 100644
--- a/exercises/02.variables/01.problem.let-and-const/README.mdx
+++ b/exercises/02.variables/01.problem.let-and-const/README.mdx
@@ -8,11 +8,31 @@ product prices).
π¨ Open and:
-1. Create a `const` for `TAX_RATE` set to `0.08`
-2. Create a `let` for `cartTotal` starting at `0`
-3. Create `const` variables for product prices: `bookPrice`, `muffinPrice`, and `laptopPrice`
-4. Add items to the cart by updating `cartTotal`
-5. Try to reassign `TAX_RATE` and see what TypeScript says
+1. Create a `const` named `TAX_RATE` set to `0.08`
+2. Create a `let` named `cartTotal` starting at `0`
+3. Create `const` product prices with these exact values:
+ - `bookPrice` = `15.99`
+ - `muffinPrice` = `4.5`
+ - `laptopPrice` = `999.99`
+4. Add the book and the muffin to the cart by updating `cartTotal` (do **not**
+ add the laptop for this step)
+5. Create `finalTotal` as the cart subtotal plus 8% tax (`TAX_RATE`)
+6. Try to reassign `TAX_RATE` (keep it commented after you see the TypeScript
+ error) and export your results
+
+## Required exports
+
+Export these names so the tests can verify your work:
+
+- `TAX_RATE`
+- `cartTotal`
+- `finalTotal`
+
+## Completion criteria (with the fixtures above)
+
+- `TAX_RATE` is `0.08`
+- `cartTotal` is `20.49` (book + muffin only)
+- `finalTotal` is `22.1292` (subtotal + 8% tax)
π° By convention, constants that represent fixed values are often UPPER_CASE:
diff --git a/exercises/02.variables/01.problem.let-and-const/index.ts b/exercises/02.variables/01.problem.let-and-const/index.ts
index e05fb69..ae3ec63 100644
--- a/exercises/02.variables/01.problem.let-and-const/index.ts
+++ b/exercises/02.variables/01.problem.let-and-const/index.ts
@@ -6,18 +6,18 @@
// π¨ Create a variable `cartTotal` using `let`, starting at 0
// π¨ Create constants for product prices:
-// - bookPrice is $15.99
-// - muffinPrice is $4.5
-// - laptopPrice is $999.99
-// π° note, TypeScript doesn't know/care about whether the number represents
-// money, a count, or anything, so you don't use the dollar sign in this syntax
+// - bookPrice is 15.99
+// - muffinPrice is 4.5
+// - laptopPrice is 999.99
+// π° TypeScript doesn't know/care whether the number represents money or a
+// count, so you don't use a dollar sign in the syntax
// π¨ Add the book to the cart (update cartTotal)
// π¨ Add the muffin to the cart (update cartTotal)
+// π° Leave the laptop out of the cart for this exercise
-// π¨ Calculate the final total with tax
-// π° Include tax when computing the final total
+// π¨ Create `finalTotal` as cartTotal plus 8% tax using TAX_RATE
// π¨ Try uncommenting the line below - what happens?
// TAX_RATE = 0.10
@@ -27,5 +27,5 @@
// console.log('Tax:', cartTotal * TAX_RATE)
// console.log('Final total:', finalTotal)
-// π¨ Export your variables so we can verify your work
+// π¨ Export TAX_RATE, cartTotal, and finalTotal so we can verify your work
// export { TAX_RATE, cartTotal, finalTotal }
diff --git a/exercises/02.variables/01.solution.let-and-const/index.test.ts b/exercises/02.variables/01.solution.let-and-const/index.test.ts
index 14cb84c..6a47dd5 100644
--- a/exercises/02.variables/01.solution.let-and-const/index.test.ts
+++ b/exercises/02.variables/01.solution.let-and-const/index.test.ts
@@ -28,7 +28,7 @@ await test('cartTotal should be calculated correctly', () => {
// cartTotal = bookPrice + muffinPrice = 15.99 + 4.5 = 20.49
assert.ok(
Math.abs(solution.cartTotal - 20.49) < Math.pow(10, -2),
- 'π¨ cartTotal should be 20.49 - add bookPrice and muffinPrice together',
+ 'π¨ cartTotal should be 20.49 - add the book and muffin prices (not the laptop)',
)
})
@@ -43,6 +43,6 @@ await test('finalTotal should include tax', () => {
// finalTotal = cartTotal + cartTotal * TAX_RATE = 20.49 + 20.49 * 0.08 = 22.1292
assert.ok(
Math.abs(solution.finalTotal - 22.1292) < Math.pow(10, -4),
- 'π¨ finalTotal should be 22.1292 - add the tax (cartTotal * TAX_RATE) to cartTotal',
+ 'π¨ finalTotal should be 22.1292 - subtotal plus 8% tax',
)
})
diff --git a/exercises/02.variables/02.problem.reassignment-vs-mutation/README.mdx b/exercises/02.variables/02.problem.reassignment-vs-mutation/README.mdx
index 6c759b3..87ce42e 100644
--- a/exercises/02.variables/02.problem.reassignment-vs-mutation/README.mdx
+++ b/exercises/02.variables/02.problem.reassignment-vs-mutation/README.mdx
@@ -24,12 +24,31 @@ obj.count = 2 // The object itself is modified (mutated)
properties on a `const` object.
-π¨ Open and:
+π¨ Open . The starter already declares:
-1. Try to reassign the `const` object (see the error)
-2. Mutate the `const` object by changing `age` to `31` and `city` to
- `'Portland'`
-3. Observe that mutation works even with `const`
+```ts
+const person = { name: 'Alice', age: 30, city: 'Seattle' }
+```
+
+Complete these tasks:
+
+1. Try to reassign `person` to a new object (uncomment the line and observe the
+ TypeScript error), then leave that reassignment commented out
+2. Mutate `person` so `age` becomes `31` and `city` becomes `'Portland'`
+ (`name` stays `'Alice'`)
+3. Export `person`
+
+## Required exports
+
+- `person`
+
+## Completion criteria
+
+After mutation, `person` must deep-equal:
+
+```ts
+{ name: 'Alice', age: 31, city: 'Portland' }
+```
π° Mutation means changing properties on the existing object (not replacing the
object itself).
diff --git a/exercises/02.variables/02.problem.reassignment-vs-mutation/index.ts b/exercises/02.variables/02.problem.reassignment-vs-mutation/index.ts
index 54d7285..40b33bf 100644
--- a/exercises/02.variables/02.problem.reassignment-vs-mutation/index.ts
+++ b/exercises/02.variables/02.problem.reassignment-vs-mutation/index.ts
@@ -19,5 +19,5 @@ console.log('Modified person:', person)
// The variable person always points to the SAME object,
// but the properties of that object can change.
-// π¨ Export your variable so we can verify your work
+// π¨ Export person so we can verify your work
// export { person }
diff --git a/exercises/03.primitive-types/01.problem.numbers-and-strings/README.mdx b/exercises/03.primitive-types/01.problem.numbers-and-strings/README.mdx
index 4d28c75..54c393a 100644
--- a/exercises/03.primitive-types/01.problem.numbers-and-strings/README.mdx
+++ b/exercises/03.primitive-types/01.problem.numbers-and-strings/README.mdx
@@ -13,11 +13,24 @@ We need to track:
π¨ Open and complete the following tasks:
-1. Create a variable `price` with type `number` set to `29.99`
-2. Create a variable `productName` with type `string` set to `"TypeScript Guide"`
-3. Create a variable `quantity` with type `number` set to `100`
-4. Create a `description` variable that uses a template literal to combine the
- product info
+1. Create `price` with type `number` set to `29.99`
+2. Create `productName` with type `string` set to `"TypeScript Guide"`
+3. Create `quantity` with type `number` set to `100`
+4. Create `description` as a string (prefer a template literal) with this exact
+ value:
+ `Product: TypeScript Guide | Price: $29.99 | In Stock: 100`
+
+## Required exports
+
+Export: `price`, `productName`, `quantity`, `description`
+
+## Completion criteria
+
+- `price` is the number `29.99`
+- `productName` is `"TypeScript Guide"`
+- `quantity` is the number `100`
+- `description` matches the exact formatted string above (including `$`, spaces,
+ and `|` separators)
π° Template literals let you embed expressions inside a string.
diff --git a/exercises/03.primitive-types/01.problem.numbers-and-strings/index.ts b/exercises/03.primitive-types/01.problem.numbers-and-strings/index.ts
index a63f4d5..3bdf4d3 100644
--- a/exercises/03.primitive-types/01.problem.numbers-and-strings/index.ts
+++ b/exercises/03.primitive-types/01.problem.numbers-and-strings/index.ts
@@ -7,7 +7,7 @@
// π¨ Create a variable `quantity` with type `number` set to 100
-// π¨ Create a `description` using a template literal that outputs:
+// π¨ Create a `description` using a template literal that equals exactly:
// "Product: TypeScript Guide | Price: $29.99 | In Stock: 100"
// β
These console.logs will verify your work
@@ -16,5 +16,5 @@
// console.log('Quantity:', quantity)
// console.log('Description:', description)
-// π¨ Export your variables so we can verify your work
+// π¨ Export price, productName, quantity, and description
// export { price, productName, quantity, description }
diff --git a/exercises/03.primitive-types/02.problem.comparisons/README.mdx b/exercises/03.primitive-types/02.problem.comparisons/README.mdx
index a1f8782..ff83aa4 100644
--- a/exercises/03.primitive-types/02.problem.comparisons/README.mdx
+++ b/exercises/03.primitive-types/02.problem.comparisons/README.mdx
@@ -46,11 +46,36 @@ a >= b // greater than or equal
a <= b // less than or equal
```
-π¨ Open and:
+π¨ Open . The starter provides:
-1. Compare `price` (number) and `quantity` (string) with both `==` and `===`
-2. Use `!=` and `!==` to check if `a` is not equal to `b`
-3. Use `>` and `<=` to compare `a` and `b`
+- `price: number = 100`
+- `quantity: string = '100'`
+- `a: number = 10`
+- `b: number = 20`
+
+Create and export these variables:
+
+1. `looseEqual` β compare `price` and `quantity` with `==`
+2. `strictEqual` β compare `price` and `quantity` with `===`
+3. `notEqualLoose` β whether `a` is not equal to `b` using `!=`
+4. `notEqualStrict` β whether `a` is not equal to `b` using `!==`
+5. `isGreater` β whether `b` is greater than `a`
+6. `isLessOrEqual` β whether `a` is less than or equal to `b`
+
+For the `price`/`quantity` comparisons, add a `// @ts-expect-error` comment on
+the line above each comparison so TypeScript allows comparing different types
+(that's part of the lesson).
+
+## Required exports
+
+`looseEqual`, `strictEqual`, `notEqualLoose`, `notEqualStrict`, `isGreater`,
+`isLessOrEqual`
+
+## Completion criteria
+
+Each export is a boolean produced by the comparison described above. Log or
+inspect the values with these fixtures so you can see how loose vs strict
+equality (and the other operators) evaluateβdon't hardcode the answers.
π [MDN - Equality comparisons](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness)
diff --git a/exercises/03.primitive-types/02.problem.comparisons/index.ts b/exercises/03.primitive-types/02.problem.comparisons/index.ts
index c7c8879..5b9a443 100644
--- a/exercises/03.primitive-types/02.problem.comparisons/index.ts
+++ b/exercises/03.primitive-types/02.problem.comparisons/index.ts
@@ -4,11 +4,11 @@
const price: number = 100
const quantity: string = '100'
-// π¨ Create a variable `looseEqual` that compares price and quantity with ==
-// add a @ts-expect-error comment to suppress the TypeScript error (that's the point!)
+// π¨ Create `looseEqual` that compares price and quantity with ==
+// π° Add a @ts-expect-error comment above the comparison (TypeScript will warn)
-// π¨ Create a variable `strictEqual` that compares price and quantity with ===
-// add a @ts-expect-error comment to suppress the TypeScript error (that's the point!)
+// π¨ Create `strictEqual` that compares price and quantity with ===
+// π° Add a @ts-expect-error comment above the comparison
// π¨ Log both results to see the difference
// console.log('Loose equality (==):', looseEqual)
@@ -17,18 +17,18 @@ const quantity: string = '100'
const a: number = 10
const b: number = 20
-// π¨ Create a variable `notEqualLoose` using != to check if a is not equal to b
+// π¨ Create `notEqualLoose` using != to check if a is not equal to b
-// π¨ Create a variable `notEqualStrict` using !== to check if a is not equal to b
+// π¨ Create `notEqualStrict` using !== to check if a is not equal to b
-// π¨ Create a variable `isGreater` that checks if b is greater than a
+// π¨ Create `isGreater` that checks if b is greater than a
-// π¨ Create a variable `isLessOrEqual` that checks if a is less than or equal to b
+// π¨ Create `isLessOrEqual` that checks if a is less than or equal to b
// console.log('a != b:', notEqualLoose)
// console.log('a !== b:', notEqualStrict)
// console.log('b > a:', isGreater)
// console.log('a <= b:', isLessOrEqual)
-// π¨ Export your variables so we can verify your work
+// π¨ Export looseEqual, strictEqual, notEqualLoose, notEqualStrict, isGreater, isLessOrEqual
// export { looseEqual, strictEqual, notEqualLoose, notEqualStrict, isGreater, isLessOrEqual }
diff --git a/exercises/03.primitive-types/03.problem.booleans-and-comparisons/README.mdx b/exercises/03.primitive-types/03.problem.booleans-and-comparisons/README.mdx
index 1314cf6..1901558 100644
--- a/exercises/03.primitive-types/03.problem.booleans-and-comparisons/README.mdx
+++ b/exercises/03.primitive-types/03.problem.booleans-and-comparisons/README.mdx
@@ -25,21 +25,35 @@ const result2 = a && (b || c) // || happens first, then &&
const result3 = (a || b) && c // || happens first, then &&
```
-π¨ Open and complete the following tasks:
+π¨ Open . The starter provides:
-1. Create a variable `isAvailable` with type `boolean` set to `true`
-2. Create a variable `hasDiscount` that's `true` when the price is under 50
-3. Create a variable `canPurchase` that's `true` when the item is available AND
- in stock
-4. Create a variable `isNotAvailable` that's the opposite of `isAvailable` using
- the `!` operator
+- `price: number = 29.99`
+- `stockCount: number = 100`
+
+Complete the following tasks:
+
+1. Create `isAvailable` with type `boolean` set to `true`
+2. Create `hasDiscount` that is `true` when `price` is under `50`
+3. Create `canPurchase` that is `true` when `isAvailable` is true **and**
+ `stockCount` is greater than `0`
+4. Create `isNotAvailable` that is the opposite of `isAvailable`
+
+After the variables exist, remove the `// @ts-expect-error` comments above the
+`console.log` lines so the file typechecks cleanly.
+
+## Required exports
+
+`isAvailable`, `hasDiscount`, `canPurchase`, `isNotAvailable`
+
+## Completion criteria
+
+All four exports should be real booleans (`typeof` is `"boolean"`), not strings.
+Use the fixtures and rules above to check your results (for example by logging).
π [MDN - Logical operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators)
- You'll notice `// @ts-expect-error` comments in the code. This tells
- TypeScript to ignore the type error on the next line. Once you've created the
- variables (`isAvailable`, `isOnSale`, `hasDiscount`, `canPurchase`,
- `isNotAvailable`), you can remove these comments and the code will work
- correctly!
+ You'll notice `// @ts-expect-error` comments in the starter. Those suppress
+ errors for names that don't exist yet. Once you've created `isAvailable`,
+ `hasDiscount`, `canPurchase`, and `isNotAvailable`, remove those comments.
diff --git a/exercises/03.primitive-types/03.problem.booleans-and-comparisons/index.ts b/exercises/03.primitive-types/03.problem.booleans-and-comparisons/index.ts
index 745e585..e6b797a 100644
--- a/exercises/03.primitive-types/03.problem.booleans-and-comparisons/index.ts
+++ b/exercises/03.primitive-types/03.problem.booleans-and-comparisons/index.ts
@@ -22,5 +22,5 @@ console.log('Can Purchase:', canPurchase)
// @ts-expect-error - π£ remove this comment
console.log('Is Not Available:', isNotAvailable)
-// π¨ Export your variables so we can verify your work
+// π¨ Export isAvailable, hasDiscount, canPurchase, and isNotAvailable
// export { isAvailable, hasDiscount, canPurchase, isNotAvailable }
diff --git a/exercises/03.primitive-types/03.solution.booleans-and-comparisons/index.test.ts b/exercises/03.primitive-types/03.solution.booleans-and-comparisons/index.test.ts
index 0eb67a4..f2ad282 100644
--- a/exercises/03.primitive-types/03.solution.booleans-and-comparisons/index.test.ts
+++ b/exercises/03.primitive-types/03.solution.booleans-and-comparisons/index.test.ts
@@ -33,7 +33,7 @@ await test('hasDiscount should be true (price < 50)', () => {
assert.strictEqual(
solution.hasDiscount,
true,
- 'π¨ hasDiscount should be true when price < 50 - use a comparison: price < 50',
+ 'π¨ hasDiscount should be true when price is under 50 - use a comparison against price',
)
})
@@ -41,7 +41,7 @@ await test('hasDiscount should be a boolean type', () => {
assert.strictEqual(
typeof solution.hasDiscount,
'boolean',
- 'π¨ hasDiscount should be a boolean type - use a comparison: price < 50',
+ 'π¨ hasDiscount should be a boolean type - compare price to 50',
)
})
@@ -56,12 +56,12 @@ await test('canPurchase should be true (isAvailable && stockCount > 0)', () => {
assert.strictEqual(
solution.canPurchase,
true,
- 'π¨ canPurchase should be true when both isAvailable is true AND stockCount > 0 - use the && operator',
+ 'π¨ canPurchase should be true when the item is available and stockCount is greater than 0',
)
assert.strictEqual(
typeof solution.canPurchase,
'boolean',
- 'π¨ canPurchase should be a boolean type - use a logical expression that returns true or false',
+ 'π¨ canPurchase should be a boolean type - combine the availability and stock checks',
)
})
@@ -76,11 +76,11 @@ await test('isNotAvailable should be false (!isAvailable)', () => {
assert.strictEqual(
solution.isNotAvailable,
false,
- 'π¨ isNotAvailable should be false (the opposite of isAvailable which is true) - use the ! operator: !isAvailable',
+ 'π¨ isNotAvailable should be false (the opposite of isAvailable, which is true)',
)
assert.strictEqual(
typeof solution.isNotAvailable,
'boolean',
- 'π¨ isNotAvailable should be a boolean type - use the ! operator to invert isAvailable',
+ 'π¨ isNotAvailable should be a boolean type - invert isAvailable',
)
})
diff --git a/exercises/03.primitive-types/04.problem.null-and-undefined/README.mdx b/exercises/03.primitive-types/04.problem.null-and-undefined/README.mdx
index 330188b..f03994c 100644
--- a/exercises/03.primitive-types/04.problem.null-and-undefined/README.mdx
+++ b/exercises/03.primitive-types/04.problem.null-and-undefined/README.mdx
@@ -18,9 +18,20 @@ const deletedAt = null // intentionally empty
π¨ Open and:
-1. Create a variable `discountCode` set to `undefined`
-2. Create a variable `lastPurchaseDate` set to `null`
-3. Log both variables to see their values
+1. Create `discountCode` set explicitly to `undefined`
+2. Create `lastPurchaseDate` set explicitly to `null`
+3. Optionally log both variables so you can see their values in the console
+4. Export both variables
+
+## Required exports
+
+- `discountCode`
+- `lastPurchaseDate`
+
+## Completion criteria
+
+- `discountCode` is `undefined`
+- `lastPurchaseDate` is `null`
π [TypeScript Handbook - Null and Undefined](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#null-and-undefined)
diff --git a/exercises/03.primitive-types/04.problem.null-and-undefined/index.ts b/exercises/03.primitive-types/04.problem.null-and-undefined/index.ts
index c158cb0..cced6f4 100644
--- a/exercises/03.primitive-types/04.problem.null-and-undefined/index.ts
+++ b/exercises/03.primitive-types/04.problem.null-and-undefined/index.ts
@@ -9,5 +9,5 @@
// console.log('discountCode:', discountCode)
// console.log('lastPurchaseDate:', lastPurchaseDate)
-// π¨ Export your variables so we can verify your work
+// π¨ Export discountCode and lastPurchaseDate
// export { discountCode, lastPurchaseDate }
diff --git a/exercises/03.primitive-types/05.problem.bigint-and-symbol/README.mdx b/exercises/03.primitive-types/05.problem.bigint-and-symbol/README.mdx
index cec4838..8b8d6e9 100644
--- a/exercises/03.primitive-types/05.problem.bigint-and-symbol/README.mdx
+++ b/exercises/03.primitive-types/05.problem.bigint-and-symbol/README.mdx
@@ -40,9 +40,26 @@ Symbols are often used for "hidden" object properties or library-internal keys.
π¨ Open and:
-1. Create a bigint literal with the `n` suffix
-2. Perform arithmetic with bigint values
-3. Create symbols and observe their uniqueness
+1. Create `largeNumber` as the bigint `9007199254740993n`
+2. Create `anotherLarge` as the bigint `1000000000000000000n`
+3. Create `sum` by adding those two bigints
+4. Create `userId` with `Symbol('user-id')`
+5. Create `anotherId` with the same description `Symbol('user-id')`
+6. Create `areEqual` by comparing `userId === anotherId`, then inspect the
+ result
+7. Export all six names
+
+## Required exports
+
+`largeNumber`, `anotherLarge`, `sum`, `userId`, `anotherId`, `areEqual`
+
+## Completion criteria
+
+- `largeNumber` is `9007199254740993n` (`typeof` `"bigint"`)
+- `anotherLarge` is `1000000000000000000n`
+- `sum` equals the sum of those two bigints
+- `userId` and `anotherId` are both symbols
+- `areEqual` reflects whether those two symbols compare equal with `===`
π° BigInt literals use the `n` suffix.
diff --git a/exercises/03.primitive-types/05.problem.bigint-and-symbol/index.ts b/exercises/03.primitive-types/05.problem.bigint-and-symbol/index.ts
index 48ddf4c..b912e0d 100644
--- a/exercises/03.primitive-types/05.problem.bigint-and-symbol/index.ts
+++ b/exercises/03.primitive-types/05.problem.bigint-and-symbol/index.ts
@@ -12,15 +12,14 @@
// π¨ Create another symbol called `anotherId` with the same description 'user-id'
-// π¨ Create a variable `areEqual` that compares userId === anotherId
-// This will be false because each Symbol() call creates a unique value!
+// π¨ Create `areEqual` that compares userId === anotherId
// Test - uncomment when ready
// console.log('Large number:', largeNumber)
// console.log('Sum of bigints:', sum)
// console.log('userId:', userId)
// console.log('anotherId:', anotherId)
-// console.log('Are symbols equal?', areEqual) // false
+// console.log('Are symbols equal?', areEqual)
-// π¨ Export your variables so we can verify your work
+// π¨ Export largeNumber, anotherLarge, sum, userId, anotherId, and areEqual
// export { largeNumber, anotherLarge, sum, userId, anotherId, areEqual }
diff --git a/exercises/03.primitive-types/05.solution.bigint-and-symbol/index.test.ts b/exercises/03.primitive-types/05.solution.bigint-and-symbol/index.test.ts
index c4af6a0..463d976 100644
--- a/exercises/03.primitive-types/05.solution.bigint-and-symbol/index.test.ts
+++ b/exercises/03.primitive-types/05.solution.bigint-and-symbol/index.test.ts
@@ -13,7 +13,7 @@ await test('largeNumber should be a bigint with correct value', () => {
assert.strictEqual(
typeof solution.largeNumber,
'bigint',
- 'π¨ largeNumber should be type bigint - use the n suffix: 9007199254740993n',
+ 'π¨ largeNumber should be type bigint (use a bigint literal)',
)
assert.strictEqual(
solution.largeNumber,
@@ -73,7 +73,7 @@ await test('userId should be a symbol', () => {
assert.strictEqual(
typeof solution.userId,
'symbol',
- 'π¨ userId should be type symbol - use Symbol("user-id")',
+ 'π¨ userId should be type symbol with description "user-id"',
)
})
diff --git a/exercises/03.primitive-types/06.problem.truthy-falsy/README.mdx b/exercises/03.primitive-types/06.problem.truthy-falsy/README.mdx
index 2e2e58f..c4dfdcd 100644
--- a/exercises/03.primitive-types/06.problem.truthy-falsy/README.mdx
+++ b/exercises/03.primitive-types/06.problem.truthy-falsy/README.mdx
@@ -17,16 +17,40 @@ Falsy values:
You can convert any value to a boolean with `Boolean(value)` or `!!value`.
-π¨ Open and:
-
-1. Create `hasUsername` based on the truthiness of `username`
-2. Create `hasNickname` based on the truthiness of `nickname`
-3. Create `hasAge` based on the truthiness of `age`
-4. Create `hasNotes` based on the truthiness of `notes`
-5. Create `canCheckout` that's `true` when `cartTotal` is truthy **and**
- `hasAcceptedTerms` is true
-6. Create `canCreateAccount` that's `true` when `hasUsername`, `email`, and
- `password` are all truthy
+π¨ Open . The starter provides these fixtures:
+
+| Name | Value |
+| ------------------ | -------------------- |
+| `username` | `'kent'` |
+| `nickname` | `''` (empty string) |
+| `age` | `0` |
+| `email` | `'kent@epicweb.dev'` |
+| `password` | `''` (empty string) |
+| `notes` | `undefined` |
+| `cartTotal` | `42` |
+| `hasAcceptedTerms` | `false` |
+
+Create and export:
+
+1. `hasUsername` β boolean for whether `username` is truthy
+2. `hasNickname` β boolean for whether `nickname` is truthy
+3. `hasAge` β boolean for whether `age` is truthy
+4. `hasNotes` β boolean for whether `notes` is truthy
+5. `canCheckout` β `true` only when `cartTotal` is truthy **and**
+ `hasAcceptedTerms` is `true`
+6. `canCreateAccount` β `true` only when `hasUsername`, `email`, and `password`
+ are all truthy
+
+## Required exports
+
+`hasUsername`, `hasNickname`, `hasAge`, `hasNotes`, `canCheckout`,
+`canCreateAccount`
+
+## Completion criteria
+
+Each export must be a real boolean (`typeof` `"boolean"`). Use the fixtures and
+the falsy list above to reason about (or log) what each expression evaluates
+toβdon't hardcode the answers.
π° Convert values to booleans when you need a strict true/false.
diff --git a/exercises/03.primitive-types/06.problem.truthy-falsy/index.ts b/exercises/03.primitive-types/06.problem.truthy-falsy/index.ts
index 934167b..4c7f568 100644
--- a/exercises/03.primitive-types/06.problem.truthy-falsy/index.ts
+++ b/exercises/03.primitive-types/06.problem.truthy-falsy/index.ts
@@ -10,18 +10,18 @@ const notes = undefined
const cartTotal = 42
const hasAcceptedTerms = false
-// π¨ Create a variable `hasUsername` based on the truthiness of `username`
+// π¨ Create `hasUsername` as a boolean based on the truthiness of `username`
-// π¨ Create a variable `hasNickname` based on the truthiness of `nickname`
+// π¨ Create `hasNickname` as a boolean based on the truthiness of `nickname`
-// π¨ Create a variable `hasAge` based on the truthiness of `age`
+// π¨ Create `hasAge` as a boolean based on the truthiness of `age`
-// π¨ Create a variable `hasNotes` based on the truthiness of `notes`
+// π¨ Create `hasNotes` as a boolean based on the truthiness of `notes`
-// π¨ Create a variable `canCheckout` that is true when cartTotal is truthy AND
+// π¨ Create `canCheckout` that is true when cartTotal is truthy AND
// hasAcceptedTerms is true
-// π¨ Create a variable `canCreateAccount` that is true when hasUsername, email,
+// π¨ Create `canCreateAccount` that is true when hasUsername, email,
// and password are all truthy
// β
Verification
@@ -38,5 +38,5 @@ console.log('Can checkout:', canCheckout)
// @ts-expect-error - π£ remove this comment
console.log('Can create account:', canCreateAccount)
-// π¨ Export your variables so we can verify your work
+// π¨ Export hasUsername, hasNickname, hasAge, hasNotes, canCheckout, canCreateAccount
// export { hasUsername, hasNickname, hasAge, hasNotes, canCheckout, canCreateAccount }
diff --git a/exercises/03.primitive-types/06.solution.truthy-falsy/index.test.ts b/exercises/03.primitive-types/06.solution.truthy-falsy/index.test.ts
index 7bd27ce..7d89002 100644
--- a/exercises/03.primitive-types/06.solution.truthy-falsy/index.test.ts
+++ b/exercises/03.primitive-types/06.solution.truthy-falsy/index.test.ts
@@ -13,7 +13,7 @@ await test('hasUsername should be true', () => {
assert.strictEqual(
typeof solution.hasUsername,
'boolean',
- 'π¨ hasUsername should be a boolean - use Boolean(username) or !!username',
+ 'π¨ hasUsername should be a boolean based on the truthiness of username',
)
assert.strictEqual(
solution.hasUsername,
@@ -33,7 +33,7 @@ await test('hasNickname should be false', () => {
assert.strictEqual(
typeof solution.hasNickname,
'boolean',
- 'π¨ hasNickname should be a boolean - use Boolean(nickname) or !!nickname',
+ 'π¨ hasNickname should be a boolean based on the truthiness of nickname',
)
assert.strictEqual(
solution.hasNickname,
@@ -53,7 +53,7 @@ await test('hasAge should be false', () => {
assert.strictEqual(
typeof solution.hasAge,
'boolean',
- 'π¨ hasAge should be a boolean - use Boolean(age) or !!age',
+ 'π¨ hasAge should be a boolean based on the truthiness of age',
)
assert.strictEqual(
solution.hasAge,
@@ -73,7 +73,7 @@ await test('hasNotes should be false', () => {
assert.strictEqual(
typeof solution.hasNotes,
'boolean',
- 'π¨ hasNotes should be a boolean - use Boolean(notes) or !!notes',
+ 'π¨ hasNotes should be a boolean based on the truthiness of notes',
)
assert.strictEqual(
solution.hasNotes,
diff --git a/exercises/04.control-flow/01.problem.conditionals/README.mdx b/exercises/04.control-flow/01.problem.conditionals/README.mdx
index 4763d42..b097ee5 100644
--- a/exercises/04.control-flow/01.problem.conditionals/README.mdx
+++ b/exercises/04.control-flow/01.problem.conditionals/README.mdx
@@ -5,16 +5,27 @@
π¨βπΌ We're building a grade calculator for a school system. Based on a numeric
score, we need to determine the letter grade.
-π¨ Open and:
+π¨ Open . The starter sets `score` to `85`.
-1. Write an `if`/`else if`/`else` chain to determine the letter grade:
- - 90 and above: "A"
- - 80-89: "B"
- - 70-79: "C"
- - 60-69: "D"
- - Below 60: "F"
+1. Create a `grade` string using an `if`/`else if`/`else` chain:
+ - 90 and above: `"A"`
+ - 80β89: `"B"`
+ - 70β79: `"C"`
+ - 60β69: `"D"`
+ - Below 60: `"F"`
+2. Create `passed` as a boolean that is `true` when the letter grade is C or
+ above (that means grades `"A"`, `"B"`, or `"C"`)
+3. Export `score`, `grade`, and `passed`
-2. Add a check to see if the student passed (grade C or above)
+## Required exports
+
+`score`, `grade`, `passed`
+
+## Completion criteria (with `score = 85`)
+
+- `score` remains `85`
+- `grade` is `"B"`
+- `passed` is `true`
π° Check the highest ranges first so the first match wins.
diff --git a/exercises/04.control-flow/01.problem.conditionals/index.ts b/exercises/04.control-flow/01.problem.conditionals/index.ts
index 98ce63e..59ebfcd 100644
--- a/exercises/04.control-flow/01.problem.conditionals/index.ts
+++ b/exercises/04.control-flow/01.problem.conditionals/index.ts
@@ -12,11 +12,11 @@ const score: number = 85
// - 60-69: "D"
// - Below 60: "F"
-// π¨ Create a variable `passed` that is true if grade is C or above
+// π¨ Create `passed` that is true if grade is C or above (A, B, or C)
// console.log(`Score: ${score}`)
// console.log(`Grade: ${grade}`)
// console.log(`Passed: ${passed}`)
-// π¨ Export your variables so we can verify your work
+// π¨ Export score, grade, and passed
// export { score, grade, passed }
diff --git a/exercises/04.control-flow/02.problem.switch-statements/README.mdx b/exercises/04.control-flow/02.problem.switch-statements/README.mdx
index 2b80631..4a98dea 100644
--- a/exercises/04.control-flow/02.problem.switch-statements/README.mdx
+++ b/exercises/04.control-flow/02.problem.switch-statements/README.mdx
@@ -5,17 +5,26 @@
π¨βπΌ We've been using `if`/`else if` chains, but when you're checking one value
against many possible matches, a `switch` statement is often cleaner.
-π¨ Open and:
-
-1. Create a `description` variable to hold the feedback text
-2. Write a `switch` statement that checks the `grade` value and sets the
- appropriate description:
- - 'A' β "Excellent"
- - 'B' β "Good"
- - 'C' β "Satisfactory"
- - 'D' β "Needs Improvement"
- - 'F' β "Failing"
- - Any other value β "Invalid grade"
+π¨ Open . The starter sets `grade` to `'B'`.
+
+1. Create a `description` string
+2. Write a `switch` on `grade` that sets `description` to these exact values:
+ - `'A'` β `"Excellent"`
+ - `'B'` β `"Good"`
+ - `'C'` β `"Satisfactory"`
+ - `'D'` β `"Needs Improvement"`
+ - `'F'` β `"Failing"`
+ - any other value β `"Invalid grade"`
+3. Export `grade` and `description`
+
+## Required exports
+
+`grade`, `description`
+
+## Completion criteria (with `grade = 'B'`)
+
+- `grade` remains `"B"`
+- `description` is `"Good"`
π° Use `switch` with `case` branches and a `default` for all other values.
diff --git a/exercises/04.control-flow/02.problem.switch-statements/index.ts b/exercises/04.control-flow/02.problem.switch-statements/index.ts
index 26820c9..f880737 100644
--- a/exercises/04.control-flow/02.problem.switch-statements/index.ts
+++ b/exercises/04.control-flow/02.problem.switch-statements/index.ts
@@ -5,16 +5,16 @@ const grade: string = 'B'
// π¨ Create a variable `description` of type string
-// π¨ Write a switch statement on `grade`:
-// - case 'A': set description to "Excellent"
-// - case 'B': set description to "Good"
-// - case 'C': set description to "Satisfactory"
-// - case 'D': set description to "Needs Improvement"
-// - case 'F': set description to "Failing"
-// - default: set description to "Invalid grade"
-// π° Each case should avoid falling through (use `break` in each case) by adding a `break` statement
+// π¨ Write a switch statement on `grade` with these exact strings:
+// - case 'A': "Excellent"
+// - case 'B': "Good"
+// - case 'C': "Satisfactory"
+// - case 'D': "Needs Improvement"
+// - case 'F': "Failing"
+// - default: "Invalid grade"
+// π° End each case so it does not fall through to the next one
// console.log(`Grade ${grade}: ${description}`)
-// π¨ Export your variables so we can verify your work
+// π¨ Export grade and description
// export { grade, description }
diff --git a/exercises/04.control-flow/03.problem.loops/README.mdx b/exercises/04.control-flow/03.problem.loops/README.mdx
index ea45876..e2e0662 100644
--- a/exercises/04.control-flow/03.problem.loops/README.mdx
+++ b/exercises/04.control-flow/03.problem.loops/README.mdx
@@ -4,8 +4,24 @@
π¨βπΌ Let's practice a simple `for` loop by building a numbered list.
-π¨ Open and use a `for` loop to build a string
-with labels for exhibits 1 through 5. Each label should be on its own line.
+π¨ Open and:
+
+1. Create `exhibitLabels` starting as an empty string
+2. Use a `for` loop to append labels for exhibits `1` through `5`
+3. Each label must be exactly `Exhibit N` followed by a newline (`\n`), including
+ a trailing newline after exhibit 5
+
+## Required exports
+
+- `exhibitLabels`
+
+## Completion criteria
+
+`exhibitLabels` must equal exactly (note the final `\n`):
+
+```ts
+'Exhibit 1\nExhibit 2\nExhibit 3\nExhibit 4\nExhibit 5\n'
+```
## How a `for` loop works
diff --git a/exercises/04.control-flow/03.problem.loops/index.ts b/exercises/04.control-flow/03.problem.loops/index.ts
index c0f420a..94d0f77 100644
--- a/exercises/04.control-flow/03.problem.loops/index.ts
+++ b/exercises/04.control-flow/03.problem.loops/index.ts
@@ -4,10 +4,10 @@
// π¨ Create a variable `exhibitLabels` starting as an empty string
// π¨ Write a for loop that counts from 1 to 5
-// π¨ On each pass, add a line like "Exhibit 1" to the string
-// π¨ Put each label on its own line using "\n"
+// π¨ On each pass, append "Exhibit N" plus a newline ("\n")
+// π° The finished string should end with a newline after Exhibit 5
// console.log(exhibitLabels)
-// π¨ Export your variable so we can verify your work
+// π¨ Export exhibitLabels so we can verify your work
// export { exhibitLabels }
diff --git a/exercises/04.control-flow/04.problem.nested-loops/README.mdx b/exercises/04.control-flow/04.problem.nested-loops/README.mdx
index d36bf18..b873d15 100644
--- a/exercises/04.control-flow/04.problem.nested-loops/README.mdx
+++ b/exercises/04.control-flow/04.problem.nested-loops/README.mdx
@@ -5,7 +5,13 @@
π¨βπΌ Let's generate a seating chart for a small theater. Each row has multiple
seats, so we'll need a loop inside a loop.
-π¨ Open and build a string that looks like this:
+π¨ Open . The starter provides:
+
+- `rows = ['A', 'B', 'C']`
+- `seatsPerRow = 4`
+
+Build and export `seatChart` as a string that looks exactly like this
+(spaces between seats, newline after **every** row including the last):
```
A1 A2 A3 A4
@@ -13,11 +19,23 @@ B1 B2 B3 B4
C1 C2 C3 C4
```
-Each row should be on its own line using `\n`.
+As a single string value, that is:
+
+```ts
+'A1 A2 A3 A4\nB1 B2 B3 B4\nC1 C2 C3 C4\n'
+```
Use **nested `for` loops**:
-- The **outer loop** controls which row you're on
-- The **inner loop** builds the seat labels for that row
+- The **outer loop** walks the `rows` array
+- The **inner loop** builds seat numbers `1` through `seatsPerRow`
+
+## Required exports
+
+- `seatChart`
+
+## Completion criteria
+
+`seatChart` must equal the exact string above (including the trailing `\n`).
π [MDN - for statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for)
diff --git a/exercises/04.control-flow/04.problem.nested-loops/index.ts b/exercises/04.control-flow/04.problem.nested-loops/index.ts
index b3fe31c..aed79db 100644
--- a/exercises/04.control-flow/04.problem.nested-loops/index.ts
+++ b/exercises/04.control-flow/04.problem.nested-loops/index.ts
@@ -6,11 +6,11 @@ const seatsPerRow = 4
// π¨ Create a variable `seatChart` starting as an empty string
-// π¨ Use nested for loops to build the seating chart
-// π¨ Each row should include seat labels like "A1 A2 A3 A4"
-// π¨ Put each row on its own line using "\n"
+// π¨ Use nested for loops to build the seating chart from `rows` and `seatsPerRow`
+// π¨ Each row should look like "A1 A2 A3 A4" (spaces between seats)
+// π¨ End every rowβincluding the lastβwith "\n"
// console.log(seatChart)
-// π¨ Export your variable so we can verify your work
+// π¨ Export seatChart so we can verify your work
// export { seatChart }
diff --git a/exercises/04.control-flow/05.problem.ternary-operator/README.mdx b/exercises/04.control-flow/05.problem.ternary-operator/README.mdx
index f7a0a7a..aa7618f 100644
--- a/exercises/04.control-flow/05.problem.ternary-operator/README.mdx
+++ b/exercises/04.control-flow/05.problem.ternary-operator/README.mdx
@@ -33,12 +33,29 @@ if (age >= 18) {
const status = age >= 18 ? 'adult' : 'minor'
```
-π¨ Open and use the ternary operator to:
+π¨ Open . The starter provides:
-1. Create `weatherDescription` - "hot" if temperature > 30, otherwise
- "comfortable"
-2. Create `passed` - true if score >= 70, otherwise false
-3. Create `stockMessage` - "In stock" if stock > 0, otherwise "Out of stock"
+- `temperature = 25`
+- `score = 85`
+- `stock = 0`
+
+Use the ternary operator to create:
+
+1. `weatherDescription` β `"hot"` if `temperature > 30`, otherwise
+ `"comfortable"`
+2. `passed` β `true` if `score >= 70`, otherwise `false`
+3. `stockMessage` β `"In stock"` if `stock > 0`, otherwise `"Out of stock"`
+
+Export all three.
+
+## Required exports
+
+`weatherDescription`, `passed`, `stockMessage`
+
+## Completion criteria
+
+Each export follows the ternary rules above for the given fixtures. Log or
+inspect the values to confirmβdon't hardcode answers that ignore the conditions.
The ternary operator is an **expression** that produces a value, while
diff --git a/exercises/04.control-flow/05.problem.ternary-operator/index.ts b/exercises/04.control-flow/05.problem.ternary-operator/index.ts
index b3e144b..def7f9a 100644
--- a/exercises/04.control-flow/05.problem.ternary-operator/index.ts
+++ b/exercises/04.control-flow/05.problem.ternary-operator/index.ts
@@ -3,22 +3,22 @@
const temperature = 25
-// π¨ Create a variable `weatherDescription` using a ternary operator
-// It should be "hot" if temperature > 30, otherwise "comfortable"
+// π¨ Create `weatherDescription` using a ternary operator
+// "hot" if temperature > 30, otherwise "comfortable"
const score = 85
-// π¨ Create a variable `passed` using a ternary operator
-// It should be true if score >= 70, otherwise false
+// π¨ Create `passed` using a ternary operator
+// true if score >= 70, otherwise false
const stock = 0
-// π¨ Create a variable `stockMessage` using a ternary operator
-// It should be "In stock" if stock > 0, otherwise "Out of stock"
+// π¨ Create `stockMessage` using a ternary operator
+// "In stock" if stock > 0, otherwise "Out of stock"
// console.log(`Temperature: ${temperature} β ${weatherDescription}`)
// console.log(`Score: ${score} β ${passed ? 'Passed' : 'Failed'}`)
// console.log(`Stock: ${stock} β ${stockMessage}`)
-// π¨ Export your variables so we can verify your work
+// π¨ Export weatherDescription, passed, and stockMessage
// export { weatherDescription, passed, stockMessage }
diff --git a/exercises/04.control-flow/06.problem.errors/README.mdx b/exercises/04.control-flow/06.problem.errors/README.mdx
index f476574..85afb2e 100644
--- a/exercises/04.control-flow/06.problem.errors/README.mdx
+++ b/exercises/04.control-flow/06.problem.errors/README.mdx
@@ -18,15 +18,38 @@ try {
}
```
-π¨ Open and:
+π¨ Open . The starter provides:
-1. Throw an error when the input isn't a valid number
-2. Wrap the conversion in a `try`/`catch`
-3. Set `resultMessage` to show either the parsed value or the error message
+- `rawInput = 'not-a-number'`
+- `resultMessage` starting as `''`
+- `hadError` starting as `false`
+
+Parse `rawInput` as a number inside a `try`/`catch`. If the input is not a valid
+number, throw an error whose message is exactly
+`Invalid number: not-a-number` (the prefix `Invalid number: ` plus the raw
+input). On success, set `resultMessage` to describe the parsed value using the
+format `Parsed value: `. On failure, set `hadError` to `true` and set
+`resultMessage` to `Error: ` (so the thrown message appears after
+the `Error: ` prefix).
+
+Export `resultMessage` and `hadError`.
+
+## Required exports
+
+`resultMessage`, `hadError`
+
+## Completion criteria (with this fixture)
+
+- `hadError` is `true`
+- `resultMessage` is exactly `Error: Invalid number: not-a-number`
+
+Edge cases to keep in mind: valid numeric strings should succeed and set
+`resultMessage` to the success format (no error); invalid input must throw and
+be caught without crashing the program.
- In a `catch` block, the `error` value is `unknown`. Use
- `error instanceof Error` before reading `error.message`.
+ In a `catch` block, the caught value is typed as `unknown`. Narrow it before
+ you read properties like a message string.
π [MDN - throw](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw)
diff --git a/exercises/04.control-flow/06.problem.errors/index.ts b/exercises/04.control-flow/06.problem.errors/index.ts
index fb3541c..6bff107 100644
--- a/exercises/04.control-flow/06.problem.errors/index.ts
+++ b/exercises/04.control-flow/06.problem.errors/index.ts
@@ -6,11 +6,11 @@ const rawInput = 'not-a-number'
let resultMessage = ''
let hadError = false
-// π¨ Use a try/catch block to convert rawInput to a number
-// - Inside try, create parsedValue with Number(rawInput)
-// - If Number.isNaN(parsedValue), throw a new Error with message `Invalid number: ${rawInput}`
-// - If it succeeds, set resultMessage to `Parsed value: ${parsedValue}`
-// - If it throws, set hadError to true and resultMessage to `Error: ${message}`
+// π¨ Parse rawInput as a number inside try/catch
+// - Invalid input: throw an error with message "Invalid number: " + the raw input
+// - Success: resultMessage = "Parsed value: " + the parsed number
+// - Catch: hadError = true, resultMessage = "Error: " + the error message
+// π° The caught value is unknown β narrow it before reading a message
// console.log(resultMessage)
diff --git a/exercises/05.functions/01.problem.function-declaration/README.mdx b/exercises/05.functions/01.problem.function-declaration/README.mdx
index af33e0b..ea1c257 100644
--- a/exercises/05.functions/01.problem.function-declaration/README.mdx
+++ b/exercises/05.functions/01.problem.function-declaration/README.mdx
@@ -13,8 +13,20 @@ function getFavoriteNumber(): number {
}
```
-π¨ Open and create `getMessage` that returns the
-string `"Hello, functions!"`, with an explicit return type.
+π¨ Open and:
+
+1. Create a function declaration named `getMessage`
+2. Give it an explicit return type of `string`
+3. Return exactly `"Hello, functions!"`
+4. Export `getMessage`
+
+## Required exports
+
+- `getMessage`
+
+## Completion criteria
+
+- `getMessage()` returns `"Hello, functions!"`
π° Remember to return a string and annotate the return type.
diff --git a/exercises/05.functions/01.problem.function-declaration/index.ts b/exercises/05.functions/01.problem.function-declaration/index.ts
index 48d1318..788e820 100644
--- a/exercises/05.functions/01.problem.function-declaration/index.ts
+++ b/exercises/05.functions/01.problem.function-declaration/index.ts
@@ -1,11 +1,12 @@
// Function Declarations
// A named function that returns a value
-// π¨ Create a function named `getMessage` that returns "Hello, functions!"
-// Make sure to add an explicit return type of string.
+// π¨ Create a function declaration named `getMessage`
+// - Explicit return type: string
+// - Returns exactly "Hello, functions!"
// β
Test your function
// console.log(getMessage()) // "Hello, functions!"
-// π¨ Export your function so we can verify your work
+// π¨ Export getMessage
// export { getMessage }
diff --git a/exercises/05.functions/02.problem.parameters/README.mdx b/exercises/05.functions/02.problem.parameters/README.mdx
index 9a5e448..694e729 100644
--- a/exercises/05.functions/02.problem.parameters/README.mdx
+++ b/exercises/05.functions/02.problem.parameters/README.mdx
@@ -5,15 +5,30 @@
π¨βπΌ We need utility functions for our e-commerce platform. Let's focus on
functions that accept clear inputs and return the right type.
-π¨ Open and create these functions:
+π¨ Open and create these exported functions with
+typed parameters and explicit return types:
-1. `calculateTax(amount: number, rate: number)` - Returns the tax amount
-2. `formatPrice(cents: number)` - Converts cents to dollar string (e.g., 1999 β
- "$19.99")
-3. `applyDiscount(price: number, discountPercent: number)` - Returns discounted
- price
+1. `calculateTax(amount: number, rate: number): number` β returns the tax amount
+ for the given amount and rate. Examples: `calculateTax(100, 0.08)` β `8`;
+ `calculateTax(50, 0.1)` β `5`
-Return values are already familiar from 5.1βfocus on **parameter types** here,
-but keep the return types explicit too.
+2. `formatPrice(cents: number): string` β converts whole cents into a dollar
+ string with a `$` prefix and exactly two decimal places. Examples:
+ `formatPrice(1999)` β `"$19.99"`; `formatPrice(100)` β `"$1.00"`;
+ `formatPrice(50)` β `"$0.50"`
+
+3. `applyDiscount(price: number, discountPercent: number): number` β returns the
+ price after a percentage discount is applied. Examples:
+ `applyDiscount(100, 20)` β `80`; `applyDiscount(50, 10)` β `45`;
+ `applyDiscount(200, 25)` β `150`
+
+## Required exports
+
+`calculateTax`, `formatPrice`, `applyDiscount`
+
+## Completion criteria
+
+The examples above must all pass. Prefer keeping return types explicit even
+though this step focuses on parameter types.
π [TypeScript Handbook - More on Functions](https://www.typescriptlang.org/docs/handbook/2/functions.html)
diff --git a/exercises/05.functions/02.problem.parameters/index.ts b/exercises/05.functions/02.problem.parameters/index.ts
index 893f496..fd15073 100644
--- a/exercises/05.functions/02.problem.parameters/index.ts
+++ b/exercises/05.functions/02.problem.parameters/index.ts
@@ -1,22 +1,20 @@
// E-commerce Utility Functions
// Creating functions with typed parameters and return values
-// π¨ Create a function `calculateTax` that:
-// - Takes `amount` (number) and `rate` (number)
-// - Returns the tax amount (amount * rate)
+// π¨ Create `calculateTax(amount: number, rate: number): number`
+// π° Examples: (100, 0.08) β 8; (50, 0.1) β 5
-// π¨ Create a function `formatPrice` that:
-// - Takes `cents` (number)
-// - Returns a formatted dollar string like "$19.99"
+// π¨ Create `formatPrice(cents: number): string`
+// π° "$" prefix and exactly two decimal places
+// Examples: 1999 β "$19.99", 100 β "$1.00", 50 β "$0.50"
-// π¨ Create a function `applyDiscount` that:
-// - Takes `price` (number) and `discountPercent` (number)
-// - Returns the discounted price
+// π¨ Create `applyDiscount(price: number, discountPercent: number): number`
+// π° Examples: (100, 20) β 80; (50, 10) β 45; (200, 25) β 150
// β
Test your functions
// console.log(calculateTax(100, 0.08)) // 8
// console.log(formatPrice(1999)) // "$19.99"
// console.log(applyDiscount(100, 20)) // 80
-// π¨ Export your functions so we can verify your work
+// π¨ Export calculateTax, formatPrice, and applyDiscount
// export { calculateTax, formatPrice, applyDiscount }
diff --git a/exercises/05.functions/02.solution.parameters/index.test.ts b/exercises/05.functions/02.solution.parameters/index.test.ts
index 86ac58b..2b70ff8 100644
--- a/exercises/05.functions/02.solution.parameters/index.test.ts
+++ b/exercises/05.functions/02.solution.parameters/index.test.ts
@@ -13,12 +13,12 @@ await test('calculateTax should calculate tax correctly', () => {
assert.strictEqual(
solution.calculateTax(100, 0.08),
8,
- 'π¨ calculateTax(100, 0.08) should return 8 - multiply the amount by the tax rate',
+ 'π¨ calculateTax(100, 0.08) should return 8',
)
assert.strictEqual(
solution.calculateTax(50, 0.1),
5,
- 'π¨ calculateTax(50, 0.1) should return 5 - multiply the amount by the tax rate',
+ 'π¨ calculateTax(50, 0.1) should return 5',
)
})
@@ -33,17 +33,17 @@ await test('formatPrice should format cents as dollars', () => {
assert.strictEqual(
solution.formatPrice(1999),
'$19.99',
- 'π¨ formatPrice(1999) should return "$19.99" - divide by 100 and format with dollar sign and 2 decimals',
+ 'π¨ formatPrice(1999) should return "$19.99"',
)
assert.strictEqual(
solution.formatPrice(100),
'$1.00',
- 'π¨ formatPrice(100) should return "$1.00" - divide by 100 and format with dollar sign and 2 decimals',
+ 'π¨ formatPrice(100) should return "$1.00"',
)
assert.strictEqual(
solution.formatPrice(50),
'$0.50',
- 'π¨ formatPrice(50) should return "$0.50" - divide by 100 and format with dollar sign and 2 decimals',
+ 'π¨ formatPrice(50) should return "$0.50"',
)
})
@@ -58,16 +58,16 @@ await test('applyDiscount should apply discount percentage', () => {
assert.strictEqual(
solution.applyDiscount(100, 20),
80,
- 'π¨ applyDiscount(100, 20) should return 80 - subtract the discount percentage from the price',
+ 'π¨ applyDiscount(100, 20) should return 80',
)
assert.strictEqual(
solution.applyDiscount(50, 10),
45,
- 'π¨ applyDiscount(50, 10) should return 45 - subtract the discount percentage from the price',
+ 'π¨ applyDiscount(50, 10) should return 45',
)
assert.strictEqual(
solution.applyDiscount(200, 25),
150,
- 'π¨ applyDiscount(200, 25) should return 150 - subtract the discount percentage from the price',
+ 'π¨ applyDiscount(200, 25) should return 150',
)
})
diff --git a/exercises/05.functions/03.problem.type-inference/README.mdx b/exercises/05.functions/03.problem.type-inference/README.mdx
index 0235dd5..65bf376 100644
--- a/exercises/05.functions/03.problem.type-inference/README.mdx
+++ b/exercises/05.functions/03.problem.type-inference/README.mdx
@@ -28,14 +28,31 @@ function add(a: number, b: number) {
π¨ Open and:
-1. Observe what TypeScript infers for each function
-2. Hover over function names to see the inferred return types
-3. Add an explicit return type where it catches a bug
+1. Hover over `multiply` and notice TypeScript infers its return type as
+ `number` without an annotation
+2. On `divide`, add an explicit return type of `: number` so TypeScript flags the
+ buggy string return
+3. Fix `divide` so dividing by zero throws an `Error` with the exact message
+ `"Cannot divide by zero"` (instead of returning a string)
+4. Create `isEven(n: number)` that returns whether `n` is even; let TypeScript
+ infer the boolean return type
+5. Export `multiply`, `divide`, and `isEven`
+
+## Required exports
+
+`multiply`, `divide`, `isEven`
+
+## Completion criteria
+
+- `multiply(4, 5)` β `20` (and other products work)
+- `divide(10, 2)` β `5`; `divide(7, 2)` β `3.5`
+- `divide(10, 0)` throws with message `"Cannot divide by zero"`
+- `isEven(4)` / `isEven(0)` β `true`; `isEven(7)` β `false`
- This exercise uses: - `throw new Error(message)` - stops execution and raises
- an error - `%` (modulo operator) - returns the remainder after division (e.g.,
- `7 % 2` returns `1`)
+ `throw new Error(message)` stops normal execution and raises an error. For
+ `isEven`, choose an arithmetic check that works for positive, negative, and
+ zero values.
π° In VS Code/Cursor, hover over a function name to see its full type signature.
diff --git a/exercises/05.functions/03.problem.type-inference/index.ts b/exercises/05.functions/03.problem.type-inference/index.ts
index 2d39d7c..165676b 100644
--- a/exercises/05.functions/03.problem.type-inference/index.ts
+++ b/exercises/05.functions/03.problem.type-inference/index.ts
@@ -17,10 +17,12 @@ function divide(a: number, b: number) {
return a / b
}
-// π¨ Fix the bug by throwing an error instead of returning a string:
+// π¨ Fix the bug by throwing an Error with message "Cannot divide by zero"
+// instead of returning a string
-// π¨ Create a function `isEven` that returns true if a number is even
-// Let TypeScript infer the return type
+// π¨ Create `isEven(n: number)` that returns true for even numbers
+// π° Let TypeScript infer the boolean return type
+// π° A number is even when dividing by 2 leaves no remainder
// β
Test
console.log(multiply(4, 5)) // 20
@@ -28,5 +30,5 @@ console.log(divide(10, 2)) // 5
// console.log(isEven(4)) // true
// console.log(isEven(7)) // false
-// π¨ Export your functions so we can verify your work
+// π¨ Export multiply, divide, and isEven
// export { multiply, divide, isEven }
diff --git a/exercises/05.functions/03.solution.type-inference/index.test.ts b/exercises/05.functions/03.solution.type-inference/index.test.ts
index bbfe3c1..529aee3 100644
--- a/exercises/05.functions/03.solution.type-inference/index.test.ts
+++ b/exercises/05.functions/03.solution.type-inference/index.test.ts
@@ -70,17 +70,17 @@ await test('isEven should return true for even numbers', () => {
assert.strictEqual(
solution.isEven(4),
true,
- 'π¨ isEven(4) should return true - check if the number modulo 2 equals 0',
+ 'π¨ isEven(4) should return true',
)
assert.strictEqual(
solution.isEven(2),
true,
- 'π¨ isEven(2) should return true - check if the number modulo 2 equals 0',
+ 'π¨ isEven(2) should return true',
)
assert.strictEqual(
solution.isEven(0),
true,
- 'π¨ isEven(0) should return true - check if the number modulo 2 equals 0',
+ 'π¨ isEven(0) should return true',
)
})
@@ -88,16 +88,16 @@ await test('isEven should return false for odd numbers', () => {
assert.strictEqual(
solution.isEven(7),
false,
- 'π¨ isEven(7) should return false - check if the number modulo 2 does not equal 0',
+ 'π¨ isEven(7) should return false',
)
assert.strictEqual(
solution.isEven(3),
false,
- 'π¨ isEven(3) should return false - check if the number modulo 2 does not equal 0',
+ 'π¨ isEven(3) should return false',
)
assert.strictEqual(
solution.isEven(1),
false,
- 'π¨ isEven(1) should return false - check if the number modulo 2 does not equal 0',
+ 'π¨ isEven(1) should return false',
)
})
diff --git a/exercises/05.functions/04.problem.arrow-functions/README.mdx b/exercises/05.functions/04.problem.arrow-functions/README.mdx
index a601a91..d1b2a00 100644
--- a/exercises/05.functions/04.problem.arrow-functions/README.mdx
+++ b/exercises/05.functions/04.problem.arrow-functions/README.mdx
@@ -31,9 +31,32 @@ const double = (n: number): number => n * 2
π¨ Open and:
-1. Convert the function declarations to arrow functions
-2. Use implicit returns where the function body is a single expression
-3. Create a function that uses a callback with arrow functions (no arrays)
+1. Convert `double` and `greet` from function declarations to arrow functions
+ with **implicit returns**
+2. Convert `calculateTotal` to an arrow function but keep a block body and
+ explicit `return` (it has multiple lines)
+3. Create an arrow function `isEven(n: number)` that returns whether `n` is even
+4. Create `applyToNumber(value: number, transform: (n: number) => number): number`
+ that applies `transform` to `value` and returns the result
+5. Create arrow functions `triple` (multiply by 3) and `square` (multiply a
+ number by itself)
+6. Export:
+ `double`, `greet`, `calculateTotal`, `isEven`, `applyToNumber`, `triple`,
+ `square`
+
+## Required exports
+
+`double`, `greet`, `calculateTotal`, `isEven`, `applyToNumber`, `triple`,
+`square`
+
+## Completion criteria
+
+- `double`, `greet`, `calculateTotal`, and `isEven` are arrow functions
+- `double(5)` β `10`; `double(0)` β `0`; `double(-3)` β `-6`
+- `greet('Alice')` β `"Hello, Alice!"`; `greet('Bob')` β `"Hello, Bob!"`
+- `calculateTotal(60, 0.1)` β `66`; `calculateTotal(100, 0.05)` β `105`
+- `isEven(4)` / `isEven(0)` β `true`; `isEven(7)` β `false`
+- `applyToNumber(5, triple)` β `15`; `applyToNumber(6, square)` β `36`
π° Implicit returns use a single expression and no braces.
diff --git a/exercises/05.functions/04.problem.arrow-functions/index.ts b/exercises/05.functions/04.problem.arrow-functions/index.ts
index acfd826..0aca132 100644
--- a/exercises/05.functions/04.problem.arrow-functions/index.ts
+++ b/exercises/05.functions/04.problem.arrow-functions/index.ts
@@ -18,17 +18,16 @@ function calculateTotal(subtotal: number, taxRate: number): number {
}
// π¨ Create an arrow function `isEven` that returns true if a number is even
-// π° Short functions can be written more concisely (use `n % 2 === 0`)
+// π° A number is even when dividing by 2 leaves no remainder
-// π¨ Create a function `applyToNumber` that:
-// - Takes a number and a transform function
-// - Returns the transformed number
-// π° Functions can accept other functions as parameters
+// π¨ Create `applyToNumber(value, transform)` that:
+// - Takes a number and a transform function `(n: number) => number`
+// - Returns the result of calling transform with that number
// π¨ Create arrow functions:
// - `triple` that multiplies a number by 3
// - `square` that multiplies a number by itself
-// Then call applyToNumber with each.
+// Then you can call applyToNumber with each.
-// π¨ Export your functions so we can verify your work
+// π¨ Export double, greet, calculateTotal, isEven, applyToNumber, triple, square
// export { double, greet, calculateTotal, isEven, applyToNumber, triple, square }
diff --git a/exercises/05.functions/04.solution.arrow-functions/index.test.ts b/exercises/05.functions/04.solution.arrow-functions/index.test.ts
index 288883d..db7b40d 100644
--- a/exercises/05.functions/04.solution.arrow-functions/index.test.ts
+++ b/exercises/05.functions/04.solution.arrow-functions/index.test.ts
@@ -12,7 +12,7 @@ await test('double is exported', () => {
await test('double should be an arrow function', () => {
assert.ok(
solution.double.toString().includes('=>'),
- 'π¨ double should be an arrow function - use const double = (n: number) => ...',
+ 'π¨ double should be an arrow function (its source should include =>)',
)
assert.strictEqual(solution.double(5), 10, 'π¨ double(5) should return 10')
assert.strictEqual(solution.double(0), 0, 'π¨ double(0) should return 0')
@@ -29,7 +29,7 @@ await test('greet is exported', () => {
await test('greet should be an arrow function', () => {
assert.ok(
solution.greet.toString().includes('=>'),
- 'π¨ greet should be an arrow function - use const greet = (name: string) => ...',
+ 'π¨ greet should be an arrow function (its source should include =>)',
)
assert.strictEqual(
solution.greet('Alice'),
diff --git a/exercises/05.functions/05.problem.jsdoc/README.mdx b/exercises/05.functions/05.problem.jsdoc/README.mdx
index f9ea258..65711c7 100644
--- a/exercises/05.functions/05.problem.jsdoc/README.mdx
+++ b/exercises/05.functions/05.problem.jsdoc/README.mdx
@@ -44,13 +44,42 @@ documentation!
| `@throws` | Documents errors the function throws |
| `@see` | Links to related documentation |
-π¨ Open and add JSDoc comments to each function.
+π¨ Open and:
+
+1. Add JSDoc above `add` with a description, `@param` for `a` and `b`, and
+ `@returns`
+2. Add JSDoc above `greet` with a description, `@param` for `name`, `@returns`,
+ and an `@example`
+3. Add JSDoc above `calculateCompoundInterest` documenting `principal`, `rate`
+ (decimal), `years`, `@returns`, and an `@example`
+4. Create and export `clamp(value: number, min: number, max: number): number`
+ that returns:
+ - `min` when `value` is below `min`
+ - `max` when `value` is above `max`
+ - `value` when it is already between `min` and `max` (inclusive)
+5. Give `clamp` complete JSDoc (description, `@param`, `@returns`, `@example`)
+
+## Required exports
+
+`add`, `greet`, `calculateCompoundInterest`, `clamp`
+
+## Completion criteria
+
+Automated tests verify behavior (not the JSDoc text itself):
+
+- `add(2, 3)` β `5`; `add(-1, 1)` β `0`
+- `greet('Alice')` β `"Hello, Alice!"`
+- `calculateCompoundInterest(1000, 0.05, 10)` β `1628.89`
+- `calculateCompoundInterest(100, 0.1, 1)` β `110`
+- `clamp(15, 0, 10)` β `10`; `clamp(-5, 0, 10)` β `0`; `clamp(5, 0, 10)` β `5`;
+ `clamp(0, 0, 10)` β `0`; `clamp(10, 0, 10)` β `10`
+
+For the learning goal: hover each function in your editor and confirm the JSDoc
+appears in the tooltip.
- Some functions in this exercise use built-in Math methods: - `Math.pow(base,
- exponent)` - raises base to the power of exponent (e.g., `Math.pow(2, 3)`
- returns 8) - `Math.max(a, b)` - returns the larger of two numbers -
- `Math.min(a, b)` - returns the smaller of two numbers
+ Some functions in this exercise use built-in Math helpers for powers and for
+ choosing the larger/smaller of two numbers when clamping a value into a range.
π° Put a brief description immediately after the opening `/**`.
diff --git a/exercises/05.functions/05.problem.jsdoc/index.ts b/exercises/05.functions/05.problem.jsdoc/index.ts
index 761aba2..d38d886 100644
--- a/exercises/05.functions/05.problem.jsdoc/index.ts
+++ b/exercises/05.functions/05.problem.jsdoc/index.ts
@@ -16,7 +16,6 @@ function add(a: number, b: number): number {
// - @param tag for the `name` parameter
// - @returns tag
// - @example tag showing how to use the function
-// π° Include an @example block that shows how to call the function
function greet(name: string): string {
return `Hello, ${name}!`
}
@@ -36,11 +35,11 @@ function calculateCompoundInterest(
return principal * Math.pow(1 + rate, years)
}
-// π¨ Create a function called `clamp` that:
-// - Takes a value, min, and max
-// - Returns the value constrained between min and max
-// - Has a complete JSDoc comment with description, @param, @returns, and @example
-// π° Use Math.min/Math.max to keep the value within range
+// π¨ Create `clamp(value, min, max)` that returns value constrained to [min, max]
+// - Below min β return min
+// - Above max β return max
+// - Otherwise β return value
+// - Add complete JSDoc: description, @param, @returns, @example
-// π¨ Export your functions so we can verify your work
+// π¨ Export add, greet, calculateCompoundInterest, and clamp
// export { add, greet, calculateCompoundInterest, clamp }
diff --git a/exercises/06.void-and-never/01.problem.void-functions/README.mdx b/exercises/06.void-and-never/01.problem.void-functions/README.mdx
index 47c7c6c..e4f2992 100644
--- a/exercises/06.void-and-never/01.problem.void-functions/README.mdx
+++ b/exercises/06.void-and-never/01.problem.void-functions/README.mdx
@@ -12,14 +12,24 @@ Examples of side effects:
- Sending data to a server
- Playing a sound
-π¨ Open and:
+π¨ Open and create these exported functions.
+Each takes a `message: string` and returns `void` (no useful return value):
-1. Create a `logInfo` function that logs a message with "[INFO]" prefix
-2. Create a `logError` function that logs with "[ERROR]" prefix
-3. Create a `logWithTimestamp` function that includes the current time
+1. `logInfo` β logs with an `[INFO]` prefix, e.g. `[INFO] Application started`
+2. `logError` β logs with an `[ERROR]` prefix, e.g. `[ERROR] Connection failed`
+3. `logWithTimestamp` β logs with an ISO timestamp in brackets, e.g.
+ `[2024-01-15T12:00:00.000Z] User logged in` (use the current time)
-π° Use `Date` to get the current time and include it in the log.
+## Required exports
-π° Void functions donβt return a value.
+`logInfo`, `logError`, `logWithTimestamp`
+
+## Completion criteria
+
+- Each function is callable and returns `undefined` (the runtime value of
+ `void`)
+- When you call them, console output uses the prefix/timestamp formats above
+
+π° Void functions don't return a valueβannotate the return type as `void`.
π [TypeScript Handbook - void](https://www.typescriptlang.org/docs/handbook/2/functions.html#void)
diff --git a/exercises/06.void-and-never/01.problem.void-functions/index.ts b/exercises/06.void-and-never/01.problem.void-functions/index.ts
index efc8e7c..e20cb72 100644
--- a/exercises/06.void-and-never/01.problem.void-functions/index.ts
+++ b/exercises/06.void-and-never/01.problem.void-functions/index.ts
@@ -1,18 +1,20 @@
// Logging System
// Functions that perform side effects return void
-// π¨ Create `logInfo` that takes a message and logs it with "[INFO]" prefix
-// π° Functions that don't return values have a special type: `void`
+// π¨ Create `logInfo(message: string): void`
+// π° Log with an "[INFO]" prefix, e.g. [INFO] Application started
-// π¨ Create `logError` that takes a message and logs it with "[ERROR]" prefix
+// π¨ Create `logError(message: string): void`
+// π° Log with an "[ERROR]" prefix
-// π¨ Create `logWithTimestamp` that takes a message and logs it with timestamp
-// π° Include the current time in the log using `new Date().toISOString()`
+// π¨ Create `logWithTimestamp(message: string): void`
+// π° Log with the current time as an ISO timestamp in brackets, then the message
+// Example shape: [2024-01-15T12:00:00.000Z] User logged in
// β
Test your functions
// logInfo('Application started')
// logError('Connection failed')
// logWithTimestamp('User logged in')
-// π¨ Export your functions so we can verify your work
+// π¨ Export logInfo, logError, and logWithTimestamp
// export { logInfo, logError, logWithTimestamp }
diff --git a/exercises/06.void-and-never/02.problem.never-type/README.mdx b/exercises/06.void-and-never/02.problem.never-type/README.mdx
index d7dd21c..0aac4dc 100644
--- a/exercises/06.void-and-never/02.problem.never-type/README.mdx
+++ b/exercises/06.void-and-never/02.problem.never-type/README.mdx
@@ -14,13 +14,29 @@ function fail(message: string): never {
TypeScript uses this to mark code paths that can't continue. A `never` function
is one that always throws or exits early.
-π¨ Open and:
+π¨ Open and create these exported functions:
-1. Create a `throwError` function that throws and returns `never`
-2. Create a `parseNumber` function that converts a string to a number, using
- `throwError("Invalid number")` if the input can't be parsed
-3. Create an `ensurePositive` function that returns the number if positive, or
- uses `throwError("Number must be positive")` if negative
+1. `throwError(message: string): never` β always throws an error using the given
+ message
+2. `parseNumber(value: string): number` β turn a string into a number; if the
+ value cannot be parsed, call `throwError` with the exact message
+ `Invalid number`; otherwise return the number
+3. `ensurePositive(value: number): number` β return the number when it is zero
+ or positive; if it is negative, call `throwError` with the exact message
+ `Number must be positive`
+
+## Required exports
+
+`throwError`, `parseNumber`, `ensurePositive`
+
+## Completion criteria
+
+- `throwError('Test error')` throws with message `Test error`
+- `parseNumber('42')` returns `42`
+- `parseNumber('not-a-number')` throws with message `Invalid number`
+- `ensurePositive(5)` returns `5`
+- `ensurePositive(0)` returns `0` (zero is allowed)
+- `ensurePositive(-1)` throws with message `Number must be positive`
The key learning here is that `parseNumber` and `ensurePositive` should
@@ -29,9 +45,4 @@ is one that always throws or exits early.
`never`-returning function call is unreachable.
-
- `Number(value)` converts a string to a number. If the string can't be parsed,
- it returns `NaN` (Not a Number). Check for `NaN` using `Number.isNaN(result)`.
-
-
π [TypeScript Handbook - never](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-never-type)
diff --git a/exercises/06.void-and-never/02.problem.never-type/index.ts b/exercises/06.void-and-never/02.problem.never-type/index.ts
index f3a8cae..ff322c9 100644
--- a/exercises/06.void-and-never/02.problem.never-type/index.ts
+++ b/exercises/06.void-and-never/02.problem.never-type/index.ts
@@ -1,22 +1,20 @@
// Understanding the Never Type
// Functions that never return
-// π¨ Create `throwError` that takes a message and throws
-// It should return `never` because it always throws
+// π¨ Create `throwError(message: string): never`
+// It should always throw an Error with that message
-// π¨ Create `parseNumber` that:
-// - Takes a string
-// - Converts it to a number with Number(...)
-// - Throws if the result is NaN
+// π¨ Create `parseNumber(value: string): number`
+// - Return the parsed number for valid numeric strings
+// - Call throwError('Invalid number') when the value cannot be parsed
-// π¨ Create `ensurePositive` that:
-// - Takes a number
-// - Throws if the number is negative
-// - Returns the number if it's valid
+// π¨ Create `ensurePositive(value: number): number`
+// - Return the number when it is zero or positive
+// - Call throwError('Number must be positive') when it is negative
// β
Test
// console.log(parseNumber('42'))
// console.log(ensurePositive(5))
-// π¨ Export your functions so we can verify your work
+// π¨ Export throwError, parseNumber, and ensurePositive
// export { throwError, parseNumber, ensurePositive }
diff --git a/exercises/06.void-and-never/02.solution.never-type/index.test.ts b/exercises/06.void-and-never/02.solution.never-type/index.test.ts
index 3ee9c77..b20fcdc 100644
--- a/exercises/06.void-and-never/02.solution.never-type/index.test.ts
+++ b/exercises/06.void-and-never/02.solution.never-type/index.test.ts
@@ -13,7 +13,7 @@ await test('throwError should throw an error', () => {
assert.throws(
() => solution.throwError('Test error'),
{ message: 'Test error' },
- 'π¨ throwError should throw an error with the provided message - use throw new Error()',
+ 'π¨ throwError should throw an error with the provided message',
)
})
@@ -28,7 +28,7 @@ await test('parseNumber should parse valid numbers', () => {
assert.strictEqual(
solution.parseNumber('42'),
42,
- 'π¨ parseNumber("42") should return 42 - use Number(...) to parse the value',
+ 'π¨ parseNumber("42") should return 42',
)
})
diff --git a/extra/muffin-shop-checkout/README.mdx b/extra/muffin-shop-checkout/README.mdx
index 1950827..03f2642 100644
--- a/extra/muffin-shop-checkout/README.mdx
+++ b/extra/muffin-shop-checkout/README.mdx
@@ -6,31 +6,37 @@ clean summary for customers.
π This example sticks to the skills from the workshop: numbers, strings,
booleans, variables, functions, if/else, switch statements, and loops.
-π¨ Open and complete the following tasks:
-
-1. Build the divider string with a loop.
-2. Calculate `subtotal`.
-3. Implement `calculateDiscount`.
-4. Implement `calculateTax`.
-5. Implement `calculateTip`.
-6. Implement `calculatePickupFee` with a switch statement.
-7. Set `pickupLabel` with an if/else.
-8. Set `memberMessage` with an if/else.
-9. Calculate `total`.
-10. Make sure the receipt prints with `console.log`.
+π¨ Open and complete the helpers and values
+below. Fixture inputs (`muffinCount`, prices, `taxRate`, `tipPercent`,
+`isMember`, `pickupMethod`, and so on) are already in the file.
-π° Flip `isMember` to see the discount and message change.
-π° Try `pickupMethod` as `curbside` or `delivery` to test the switch logic.
-
-## Run the example
+## Business rules
-```sh nonumber
-npm run start --workspace examples/muffin-shop-checkout
-```
+- **Divider lines**: `buildDivider` builds the `=` / `-` banner lines by
+ repeating a character to a given length.
+- **Money display**: `formatMoney` formats an amount with a leading `$` (for
+ example `3.25` displays as `$3.25`, and `4` as `$4`).
+- **Subtotal**: sum of each line item (quantity Γ unit price for muffins and
+ scones).
+- **Member discount**: members get 10% off when the subtotal is at least `$15`;
+ otherwise the discount is `$0`.
+- **Tax**: applied to the amount after the discount, using `taxRate`.
+- **Tip**: applied to the post-discount subtotal plus tax, using `tipPercent`.
+- **Pickup fee** (use a `switch` on `pickupMethod`):
+ - `counter` β `$0`
+ - `curbside` β `$3`
+ - `delivery` β `$7`
+- **Pickup label**: show `FREE` when the fee is `$0`; otherwise show the fee with
+ `formatMoney`.
+- **Member message**: `Member discount applied` for members, otherwise
+ `Join the club for 10% off`.
+- **Total**: subtotal, minus discount, plus tax, tip, and pickup fee.
+- Print the assembled `receipt` with `console.log`.
-## What the output can look like
+## Success criteria (default fixtures)
-Here is a sample console receipt output:
+With the starter defaults (`isMember = true`, `pickupMethod = 'counter'`, etc.),
+your printed receipt should match this shape and the sample numbers below:
```text
================================
@@ -51,6 +57,17 @@ Member discount applied
================================
```
+(Floating-point display may vary slightly; the structure and labels must match.)
+
+π° Flip `isMember` to see the discount and message change.
+π° Try `pickupMethod` as `curbside` or `delivery` to test the switch logic.
+
+## Run the example
+
+```sh nonumber
+npm run start --workspace extra_muffin-shop-checkout
+```
+
## Try next
- π¨ Add a `dailySpecialCount` and `dailySpecialPrice`, then include them in the
diff --git a/extra/muffin-shop-checkout/index.ts b/extra/muffin-shop-checkout/index.ts
index b1d20b7..5789634 100644
--- a/extra/muffin-shop-checkout/index.ts
+++ b/extra/muffin-shop-checkout/index.ts
@@ -13,44 +13,38 @@ const taxRate = 0.0825
const pickupMethod = 'counter'
function buildDivider(char: string, length: number) {
- // π¨ Build and return a divider string by repeating char
- // π° Build the string by repeating the character in a loop
+ // π¨ Return a string made by repeating `char` exactly `length` times
let line = ''
return line
}
function formatMoney(amount: number) {
- // π¨ Return a string like `$4.5` using a template literal
- return `$${amount}`
+ // π¨ Format amount with a leading "$" (e.g. 3.25 β "$3.25", 4 β "$4")
+ return '$0'
}
function calculateDiscount(subtotal: number, member: boolean) {
- // π¨ If the customer is a member and subtotal is at least 15,
- // return 10% of subtotal. Otherwise return 0.
+ // π¨ Members get 10% off when subtotal is at least 15; otherwise 0
return 0
}
function calculateTax(subtotal: number, rate: number) {
- // π¨ Return subtotal multiplied by rate
+ // π¨ Return the tax for this amount and rate
return 0
}
function calculateTip(totalBeforeTip: number, percent: number) {
- // π¨ Return totalBeforeTip multiplied by percent
+ // π¨ Return the tip for this amount and percent
return 0
}
function calculatePickupFee(method: string) {
- // π¨ Use a switch statement to return:
- // 'counter' -> 0
- // 'curbside' -> 3
- // 'delivery' -> 7
+ // π¨ Use a switch: counter β 0, curbside β 3, delivery β 7
return 0
}
let subtotal = 0
-// π¨ Set subtotal using item counts and prices
-// π° Use the counts and prices to compute the subtotal
+// π¨ Set subtotal from the muffin and scone counts and prices
const discount = calculateDiscount(subtotal, isMember)
const taxableAmount = subtotal - discount
@@ -59,15 +53,14 @@ const tip = calculateTip(taxableAmount + tax, tipPercent)
const pickupFee = calculatePickupFee(pickupMethod)
let pickupLabel = ''
-// π¨ If pickupFee is 0, set pickupLabel to 'FREE'
-// otherwise set it to formatMoney(pickupFee)
+// π¨ FREE when pickupFee is 0; otherwise formatMoney(pickupFee)
let memberMessage = ''
-// π¨ If isMember is true, set memberMessage to 'Member discount applied'
-// otherwise set it to 'Join the club for 10% off'
+// π¨ Members: 'Member discount applied'
+// Guests: 'Join the club for 10% off'
let total = 0
-// π¨ Set total using subtotal, discount, tax, tip, and pickupFee
+// π¨ Combine subtotal, discount, tax, tip, and pickupFee into the final total
const header = buildDivider('=', 32)
const divider = buildDivider('-', 32)
diff --git a/extra/muffin-shop-dashboard/README.mdx b/extra/muffin-shop-dashboard/README.mdx
index 2bb73d7..79d1f0c 100644
--- a/extra/muffin-shop-dashboard/README.mdx
+++ b/extra/muffin-shop-dashboard/README.mdx
@@ -7,22 +7,50 @@ double-check totals before handing it off.
for you. You only need the workshop skills: numbers, strings, booleans,
variables, functions, if/else, switch statements, loops, and `never`.
-π¨ Open and complete the following tasks:
-
-1. Format money with a template literal.
-2. Add the `(GF)` label for gluten-free items.
-3. Sum the subtotal with a loop.
-4. Apply the member discount.
-5. Calculate tax and tip.
-6. Calculate the final total.
-7. Return the pickup fee with a switch statement.
-8. Return the pickup label with a switch statement.
-9. Format the special note when it's empty.
-10. Log the ready message.
-11. Implement `assertNever`.
-
-π° Toggle `memberStatus` or `pickupMethod` in to
-see different outputs.
+π¨ Open and implement the exported
+helpers. Function signatures are already in the file.
+
+## Business rules
+
+- **Money display**: `formatMoney` formats an amount with a leading `$` (for
+ example `4.5` displays as `$4.5`).
+- **Line items**: `buildLineItemText` shows `quantity x name`, and appends
+ ` (GF)` (leading space) when the item is gluten-free. Examples:
+ `2 x Blueberry Muffin`, `1 x Oatberry Muffin (GF)`.
+- **Subtotal**: sum of each itemβs price Γ quantity (use a loop).
+- **Member discount**: status `'member'` gets 10% off when the subtotal is at
+ least `$20`; otherwise `$0`.
+- **Tax / tip**: tax uses the taxable amount and rate; tip uses the amount before
+ tip and the tip percent.
+- **Total**: subtotal, minus discount, plus tax, tip, and pickup fee.
+- **Pickup fee** (switch): `counter` β `$0`, `curbside` β `$3`, `delivery` β `$7`.
+- **Pickup label** (switch): `Counter pickup`, `Curbside pickup`, or
+ `Delivery dropoff`. Use `assertNever` for impossible cases.
+- **Notes**: `null` or an empty string becomes `No special notes`; otherwise keep
+ the note.
+- **Ready log**: `logOrderReady` is a `void` function that logs
+ `Order ready for `.
+- **`assertNever`**: throw so TypeScript knows that branch cannot continue
+ (include the unexpected value in the error).
+
+## Success criteria
+
+- The dashboard in renders without runtime
+ errors once the helpers are implemented
+- With the default app fixtures (`member`, `curbside`, gluten-free items, empty
+ note), you should see:
+ - Line items including a `(GF)` suffix where appropriate
+ - Pickup label `Curbside pickup` and a pickup fee of `$3`
+ - Special note text `No special notes`
+ - Console log: `Order ready for Avery`
+- Toggle `memberStatus` or `pickupMethod` in
+ and confirm labels/fees/discounts update
+
+## Run the example
+
+```sh nonumber
+npm run dev --workspace extra_muffin-shop-dashboard
+```
## Try next
diff --git a/extra/muffin-shop-dashboard/src/muffin-utils.ts b/extra/muffin-shop-dashboard/src/muffin-utils.ts
index 99c2cb4..5ab4a11 100644
--- a/extra/muffin-shop-dashboard/src/muffin-utils.ts
+++ b/extra/muffin-shop-dashboard/src/muffin-utils.ts
@@ -9,39 +9,35 @@ type MemberStatus = 'member' | 'guest'
type PickupMethod = 'counter' | 'curbside' | 'delivery'
function formatMoney(amount: number) {
- // π¨ Return a string like `$4.5` using a template literal
- // π° Use a template literal to format the amount with a $ prefix
+ // π¨ Format amount with a leading "$" (e.g. 4.5 β "$4.5")
return '$0'
}
function buildLineItemText(item: OrderItem) {
- // π¨ Return a string like `2 x Blueberry Muffin (GF)`
- // π° Build the string from the item fields
- let glutenFreeLabel = ''
- // π¨ If item.isGlutenFree is true, set glutenFreeLabel to ' (GF)'
- return `${item.quantity} x ${item.name}${glutenFreeLabel}`
+ // π¨ Return "quantity x name", plus " (GF)" when the item is gluten-free
+ // Examples: "2 x Blueberry Muffin", "1 x Oatberry Muffin (GF)"
+ void item
+ return ''
}
function calculateSubtotal(items: OrderItem[]) {
- // π¨ Use a for loop to add each item total to subtotal
- // π° Multiply each item's price by its quantity
+ // π¨ Loop items and sum each line total (price Γ quantity)
let subtotal = 0
return subtotal
}
function calculateDiscount(subtotal: number, status: MemberStatus) {
- // π¨ If status is 'member' and subtotal is at least 20,
- // return 10% of subtotal. Otherwise return 0.
+ // π¨ Members get 10% off when subtotal is at least 20; otherwise 0
return 0
}
function calculateTax(taxableAmount: number, rate: number) {
- // π¨ Return taxableAmount multiplied by rate
+ // π¨ Return the tax for this amount and rate
return 0
}
function calculateTip(totalBeforeTip: number, percent: number) {
- // π¨ Return totalBeforeTip multiplied by percent
+ // π¨ Return the tip for this amount and percent
return 0
}
@@ -52,40 +48,35 @@ function calculateTotal(
tip: number,
pickupFee: number,
) {
- // π¨ Return the final total using subtotal, discount, tax, tip, and pickupFee
+ // π¨ Combine subtotal, discount, tax, tip, and pickupFee into the final total
return 0
}
function getPickupFee(method: PickupMethod) {
- // π¨ Use a switch statement to return:
- // 'counter' -> 0
- // 'curbside' -> 3
- // 'delivery' -> 7
+ // π¨ Switch: counter β 0, curbside β 3, delivery β 7
return 0
}
function getPickupLabel(method: PickupMethod) {
- // π¨ Return a label for the pickup method:
- // 'counter' -> 'Counter pickup'
- // 'curbside' -> 'Curbside pickup'
- // 'delivery' -> 'Delivery dropoff'
- // π° Use a switch statement and handle the unexpected case
+ // π¨ Switch labels:
+ // counter β 'Counter pickup'
+ // curbside β 'Curbside pickup'
+ // delivery β 'Delivery dropoff'
+ // π° Handle impossible cases with assertNever
return method
}
function formatNote(note: string | null) {
- // π¨ If note is null or an empty string, return 'No special notes'
- // otherwise return the note
+ // π¨ null or '' β 'No special notes'; otherwise return the note
return note ?? ''
}
function logOrderReady(customer: string): void {
- // π¨ Use console.log to print `Order ready for ${customer}`
+ // π¨ Log: Order ready for
}
function assertNever(value: never): never {
- // π¨ Throw an error so TypeScript knows this never happens
- // π° Throw an Error that mentions the unexpected value
+ // π¨ Throw an Error that includes the unexpected value
throw new Error('Unhandled case')
}