Skip to content

Commit c033f6e

Browse files
committed
feat: add truthy and falsy exercise with solutions and tests
- Introduced a new exercise on truthy and falsy values in JavaScript. - Added corresponding solution and test files. - Updated README files to include explanations and instructions for the new exercise. - Modified package-lock.json to include new exercise dependencies.
1 parent 7c4ab58 commit c033f6e

13 files changed

Lines changed: 286 additions & 29 deletions

File tree

exercises/03.primitive-types/03.problem.booleans-and-comparisons/index.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ const stockCount: number = 100
88

99
// 🐨 Create a variable `isOnSale` with type `boolean` set to `false`
1010

11-
// 🐨 Create a variable `hasDiscount` that's true when price is under 50
12-
// 💰 Use a comparison: price < 50
13-
1411
// 🐨 Create a variable `canPurchase` that's true when isAvailable AND stockCount > 0
1512
// 💰 Use the && operator
1613

@@ -23,8 +20,6 @@ console.log('Is Available:', isAvailable)
2320
// @ts-expect-error - 💣 remove this comment
2421
console.log('Is On Sale:', isOnSale)
2522
// @ts-expect-error - 💣 remove this comment
26-
console.log('Has Discount:', hasDiscount)
27-
// @ts-expect-error - 💣 remove this comment
2823
console.log('Can Purchase:', canPurchase)
2924
// @ts-expect-error - 💣 remove this comment
3025
console.log('Is Not Available:', isNotAvailable)

exercises/03.primitive-types/03.solution.booleans-and-comparisons/index.test.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,6 @@ await test('isAvailable should be true', () => {
2222
)
2323
})
2424

25-
await test('isOnSale is exported', () => {
26-
assert.ok(
27-
'isOnSale' in solution,
28-
'🚨 Make sure you export "isOnSale" - add: export { isAvailable, isOnSale, ... }',
29-
)
30-
})
31-
32-
await test('isOnSale should be false', () => {
33-
assert.strictEqual(
34-
solution.isOnSale,
35-
false,
36-
'🚨 isOnSale should be false - check your assignment',
37-
)
38-
assert.strictEqual(
39-
typeof solution.isOnSale,
40-
'boolean',
41-
'🚨 isOnSale should be a boolean type - use true or false, not a string',
42-
)
43-
})
44-
4525
await test('hasDiscount is exported', () => {
4626
assert.ok(
4727
'hasDiscount' in solution,

exercises/03.primitive-types/03.solution.booleans-and-comparisons/index.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ const stockCount: number = 100
66

77
const isAvailable: boolean = true
88

9-
const isOnSale: boolean = false
10-
119
const hasDiscount: boolean = price < 50
1210

1311
const canPurchase: boolean = isAvailable && stockCount > 0
@@ -16,9 +14,8 @@ const isNotAvailable: boolean = !isAvailable
1614

1715
// ✅ Verification
1816
console.log('Is Available:', isAvailable)
19-
console.log('Is On Sale:', isOnSale)
2017
console.log('Has Discount:', hasDiscount)
2118
console.log('Can Purchase:', canPurchase)
2219
console.log('Is Not Available:', isNotAvailable)
2320

24-
export { isAvailable, isOnSale, hasDiscount, canPurchase, isNotAvailable }
21+
export { isAvailable, hasDiscount, canPurchase, isNotAvailable }
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Truthy and Falsy
2+
3+
👨‍💼 We often need to decide if a value "exists" without comparing it to
4+
`null` or `undefined`. JavaScript treats some values as **falsy**, and everything
5+
else as **truthy**.
6+
7+
Falsy values:
8+
9+
- `false`
10+
- `0`, `-0`, `0n`
11+
- `''` (empty string)
12+
- `null`
13+
- `undefined`
14+
- `NaN`
15+
16+
You can convert any value to a boolean with `Boolean(value)` or `!!value`.
17+
18+
🐨 Open <InlineFile file="index.ts" /> and:
19+
20+
1. Create `hasUsername` based on the truthiness of `username`
21+
2. Create `hasNickname` based on the truthiness of `nickname`
22+
3. Create `hasAge` based on the truthiness of `age`
23+
4. Create `hasNotes` based on the truthiness of `notes`
24+
5. Create `canCheckout` that's `true` when `cartTotal` is truthy **and**
25+
`hasAcceptedTerms` is true
26+
6. Create `canCreateAccount` that's `true` when `hasUsername`, `email`, and
27+
`password` are all truthy
28+
29+
💰 Use `Boolean(value)` or `!!value` to convert to a boolean.
30+
31+
📜 [MDN - Truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy)
32+
📜 [MDN - Falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Account and Checkout Status
2+
// Using truthy and falsy values to drive decisions
3+
4+
const username = 'kent'
5+
const nickname = ''
6+
const age = 0
7+
const email = 'kent@epicweb.dev'
8+
const password = ''
9+
const notes = undefined
10+
const cartTotal = 42
11+
const hasAcceptedTerms = false
12+
13+
// 🐨 Create a variable `hasUsername` based on the truthiness of `username`
14+
// 💰 Use Boolean(username) or !!username
15+
16+
// 🐨 Create a variable `hasNickname` based on the truthiness of `nickname`
17+
18+
// 🐨 Create a variable `hasAge` based on the truthiness of `age`
19+
20+
// 🐨 Create a variable `hasNotes` based on the truthiness of `notes`
21+
22+
// 🐨 Create a variable `canCheckout` that is true when cartTotal is truthy AND
23+
// hasAcceptedTerms is true
24+
25+
// 🐨 Create a variable `canCreateAccount` that is true when hasUsername, email,
26+
// and password are all truthy
27+
28+
// ✅ Verification
29+
// @ts-expect-error - 💣 remove this comment
30+
console.log('Has username:', hasUsername)
31+
// @ts-expect-error - 💣 remove this comment
32+
console.log('Has nickname:', hasNickname)
33+
// @ts-expect-error - 💣 remove this comment
34+
console.log('Has age:', hasAge)
35+
// @ts-expect-error - 💣 remove this comment
36+
console.log('Has notes:', hasNotes)
37+
// @ts-expect-error - 💣 remove this comment
38+
console.log('Can checkout:', canCheckout)
39+
// @ts-expect-error - 💣 remove this comment
40+
console.log('Can create account:', canCreateAccount)
41+
42+
// 🐨 Export your variables so we can verify your work
43+
// export { hasUsername, hasNickname, hasAge, hasNotes, canCheckout, canCreateAccount }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "exercises_03.primitive-types_06.problem.truthy-falsy",
3+
"type": "module",
4+
"scripts": {
5+
"start": "npx @kentcdodds/log-module ./index.ts",
6+
"start:watch": "npx @kentcdodds/log-module --watch ./index.ts",
7+
"test": "node --test index.test.ts",
8+
"test:watch": "node --watch --test index.test.ts"
9+
}
10+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Truthy and Falsy
2+
3+
👨‍💼 Nice work! You just used truthy and falsy values to build boolean logic
4+
without writing explicit comparisons.
5+
6+
🦉 Remember: a boolean can be created from **any** value:
7+
8+
```ts
9+
const isPresent = Boolean(value)
10+
const alsoBoolean = !!value
11+
```
12+
13+
This is useful when you care about "has a value" rather than the specific
14+
value. We'll rely on this pattern a lot when we get into control flow.
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import assert from 'node:assert/strict'
2+
import { test } from 'node:test'
3+
import * as solution from './index.ts'
4+
5+
await test('hasUsername is exported', () => {
6+
assert.ok(
7+
'hasUsername' in solution,
8+
'🚨 Make sure you export "hasUsername" - add: export { hasUsername, ... }',
9+
)
10+
})
11+
12+
await test('hasUsername should be true', () => {
13+
assert.strictEqual(
14+
typeof solution.hasUsername,
15+
'boolean',
16+
'🚨 hasUsername should be a boolean - use Boolean(username) or !!username',
17+
)
18+
assert.strictEqual(
19+
solution.hasUsername,
20+
true,
21+
'🚨 hasUsername should be true when username is a non-empty string',
22+
)
23+
})
24+
25+
await test('hasNickname is exported', () => {
26+
assert.ok(
27+
'hasNickname' in solution,
28+
'🚨 Make sure you export "hasNickname" - add: export { ..., hasNickname, ... }',
29+
)
30+
})
31+
32+
await test('hasNickname should be false', () => {
33+
assert.strictEqual(
34+
typeof solution.hasNickname,
35+
'boolean',
36+
'🚨 hasNickname should be a boolean - use Boolean(nickname) or !!nickname',
37+
)
38+
assert.strictEqual(
39+
solution.hasNickname,
40+
false,
41+
'🚨 hasNickname should be false when nickname is an empty string',
42+
)
43+
})
44+
45+
await test('hasAge is exported', () => {
46+
assert.ok(
47+
'hasAge' in solution,
48+
'🚨 Make sure you export "hasAge" - add: export { ..., hasAge, ... }',
49+
)
50+
})
51+
52+
await test('hasAge should be false', () => {
53+
assert.strictEqual(
54+
typeof solution.hasAge,
55+
'boolean',
56+
'🚨 hasAge should be a boolean - use Boolean(age) or !!age',
57+
)
58+
assert.strictEqual(
59+
solution.hasAge,
60+
false,
61+
'🚨 hasAge should be false when age is 0',
62+
)
63+
})
64+
65+
await test('hasNotes is exported', () => {
66+
assert.ok(
67+
'hasNotes' in solution,
68+
'🚨 Make sure you export "hasNotes" - add: export { ..., hasNotes, ... }',
69+
)
70+
})
71+
72+
await test('hasNotes should be false', () => {
73+
assert.strictEqual(
74+
typeof solution.hasNotes,
75+
'boolean',
76+
'🚨 hasNotes should be a boolean - use Boolean(notes) or !!notes',
77+
)
78+
assert.strictEqual(
79+
solution.hasNotes,
80+
false,
81+
'🚨 hasNotes should be false when notes is undefined',
82+
)
83+
})
84+
85+
await test('canCheckout is exported', () => {
86+
assert.ok(
87+
'canCheckout' in solution,
88+
'🚨 Make sure you export "canCheckout" - add: export { ..., canCheckout, ... }',
89+
)
90+
})
91+
92+
await test('canCheckout should be false', () => {
93+
assert.strictEqual(
94+
typeof solution.canCheckout,
95+
'boolean',
96+
'🚨 canCheckout should be a boolean',
97+
)
98+
assert.strictEqual(
99+
solution.canCheckout,
100+
false,
101+
'🚨 canCheckout should be false when terms are not accepted',
102+
)
103+
})
104+
105+
await test('canCreateAccount is exported', () => {
106+
assert.ok(
107+
'canCreateAccount' in solution,
108+
'🚨 Make sure you export "canCreateAccount" - add: export { ..., canCreateAccount }',
109+
)
110+
})
111+
112+
await test('canCreateAccount should be false', () => {
113+
assert.strictEqual(
114+
typeof solution.canCreateAccount,
115+
'boolean',
116+
'🚨 canCreateAccount should be a boolean',
117+
)
118+
assert.strictEqual(
119+
solution.canCreateAccount,
120+
false,
121+
'🚨 canCreateAccount should be false when password is empty',
122+
)
123+
})
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Account and Checkout Status
2+
// Using truthy and falsy values to drive decisions
3+
4+
const username = 'kent'
5+
const nickname = ''
6+
const age = 0
7+
const email = 'kent@epicweb.dev'
8+
const password = ''
9+
const notes = undefined
10+
const cartTotal = 42
11+
const hasAcceptedTerms = false
12+
13+
const hasUsername = Boolean(username)
14+
const hasNickname = Boolean(nickname)
15+
const hasAge = Boolean(age)
16+
const hasNotes = Boolean(notes)
17+
const canCheckout = Boolean(cartTotal) && hasAcceptedTerms
18+
const canCreateAccount = hasUsername && Boolean(email) && Boolean(password)
19+
20+
// ✅ Verification
21+
console.log('Has username:', hasUsername)
22+
console.log('Has nickname:', hasNickname)
23+
console.log('Has age:', hasAge)
24+
console.log('Has notes:', hasNotes)
25+
console.log('Can checkout:', canCheckout)
26+
console.log('Can create account:', canCreateAccount)
27+
28+
export {
29+
hasUsername,
30+
hasNickname,
31+
hasAge,
32+
hasNotes,
33+
canCheckout,
34+
canCreateAccount,
35+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "exercises_03.primitive-types_06.solution.truthy-falsy",
3+
"type": "module",
4+
"scripts": {
5+
"start": "npx @kentcdodds/log-module ./index.ts",
6+
"start:watch": "npx @kentcdodds/log-module --watch ./index.ts",
7+
"test": "node --test index.test.ts",
8+
"test:watch": "node --watch --test index.test.ts"
9+
}
10+
}

0 commit comments

Comments
 (0)