-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Lab: Group Discount (Section 1: Composing Types: Part II)
- Loading branch information
1 parent
f1ca41d
commit 205e507
Showing
5 changed files
with
207 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Lab: Group Discount 🛍️ | ||
|
||
> **Section 1: Composing Types: Part II** | ||
We're trying to group the discounts that we offer in our online store, but we're | ||
having a tough time creating the types for these groups. Can you help us?! | ||
|
||
## Requirements | ||
|
||
We got stuck creating the `GroupedDiscounts` type, so it currently allows for `any` | ||
type of value. | ||
|
||
1. Change the `GroupedDiscounts` type into a mapped type that allows for grouping | ||
discounts by their `kind` property. | ||
2. Test that your code runs correctly with `npx tsx index.ts`. | ||
|
||
### Extra Credit | ||
|
||
The `DiscountBase` has a wide type of `string` for the `code` property, but we'd | ||
like to ensure that the discount code for each kind of discount matches a specific | ||
format. | ||
|
||
Use the existing `code` values to help you establish the formats, and then create | ||
template literal types to enforce a specific format for each kind of discount. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
type DiscountBase = { | ||
description: string; | ||
}; | ||
|
||
type PercentageDiscount = DiscountBase & { | ||
kind: "percentage"; | ||
code: `PERCENT_OFF_${number}`; | ||
percentage: number; | ||
}; | ||
|
||
type AmountDiscount = DiscountBase & { | ||
kind: "amount"; | ||
code: `AMOUNT_OFF_${number}`; | ||
amount: number; | ||
}; | ||
|
||
type QuantityDiscount = DiscountBase & { | ||
kind: "quantity"; | ||
code: `BUY_${number}_GET_${number}_FREE`; | ||
quantity: number; | ||
free: number; | ||
}; | ||
|
||
type Discount = PercentageDiscount | AmountDiscount | QuantityDiscount; | ||
|
||
// -- Discounts -- | ||
|
||
const discounts: Discount[] = [ | ||
{ | ||
code: "PERCENT_OFF_10", | ||
description: "10% off", | ||
kind: "percentage", | ||
percentage: 10, | ||
}, | ||
{ | ||
code: "AMOUNT_OFF_5", | ||
description: "$5 off", | ||
kind: "amount", | ||
amount: 5, | ||
}, | ||
{ | ||
code: "PERCENT_OFF_30", | ||
description: "30% off", | ||
kind: "percentage", | ||
percentage: 30, | ||
}, | ||
{ | ||
kind: "quantity", | ||
code: "BUY_1_GET_1_FREE", | ||
description: "Buy 1 get 1 free", | ||
quantity: 1, | ||
free: 1, | ||
}, | ||
{ | ||
kind: "amount", | ||
code: "AMOUNT_OFF_15", | ||
description: "$15 off", | ||
amount: 15, | ||
}, | ||
{ | ||
kind: "quantity", | ||
code: "BUY_3_GET_1_FREE", | ||
description: "Buy 3 get 1 free", | ||
quantity: 3, | ||
free: 1, | ||
}, | ||
]; | ||
|
||
// -- Grouped discounts -- | ||
|
||
type GroupedDiscounts = { | ||
[Key in Discount["kind"]]?: Discount[]; | ||
}; | ||
|
||
// Alternative `GroupedDiscounts` type using built-in utility types. | ||
{ | ||
type GroupedDiscounts = Partial<Record<Discount["kind"], Discount[]>>; | ||
} | ||
|
||
function groupDiscounts(discounts: Discount[]): GroupedDiscounts { | ||
const groups: GroupedDiscounts = {}; | ||
|
||
for (let discount of discounts) { | ||
groups[discount.kind] = groups[discount.kind] ?? []; | ||
groups[discount.kind]?.push(discount); | ||
} | ||
|
||
return groups; | ||
} | ||
|
||
const groupedDiscounts = groupDiscounts(discounts); | ||
|
||
console.log(groupedDiscounts); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "@total-typescript/tsconfig/tsc/no-dom/app" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
type DiscountBase = { | ||
code: string; | ||
description: string; | ||
}; | ||
|
||
type PercentageDiscount = DiscountBase & { | ||
kind: "percentage"; | ||
percentage: number; | ||
}; | ||
|
||
type AmountDiscount = DiscountBase & { | ||
kind: "amount"; | ||
amount: number; | ||
}; | ||
|
||
type QuantityDiscount = DiscountBase & { | ||
kind: "quantity"; | ||
quantity: number; | ||
free: number; | ||
}; | ||
|
||
type Discount = PercentageDiscount | AmountDiscount | QuantityDiscount; | ||
|
||
// -- Discounts -- | ||
|
||
const discounts: Discount[] = [ | ||
{ | ||
code: "PERCENT_OFF_10", | ||
description: "10% off", | ||
kind: "percentage", | ||
percentage: 10, | ||
}, | ||
{ | ||
code: "AMOUNT_OFF_5", | ||
description: "$5 off", | ||
kind: "amount", | ||
amount: 5, | ||
}, | ||
{ | ||
code: "PERCENT_OFF_30", | ||
description: "30% off", | ||
kind: "percentage", | ||
percentage: 30, | ||
}, | ||
{ | ||
kind: "quantity", | ||
code: "BUY_1_GET_1_FREE", | ||
description: "Buy 1 get 1 free", | ||
quantity: 1, | ||
free: 1, | ||
}, | ||
{ | ||
kind: "amount", | ||
code: "AMOUNT_OFF_15", | ||
description: "$15 off", | ||
amount: 15, | ||
}, | ||
{ | ||
kind: "quantity", | ||
code: "BUY_3_GET_1_FREE", | ||
description: "Buy 3 get 1 free", | ||
quantity: 3, | ||
free: 1, | ||
}, | ||
]; | ||
|
||
// -- Grouped discounts -- | ||
|
||
type GroupedDiscounts = any; | ||
|
||
function groupDiscounts(discounts: Discount[]): GroupedDiscounts { | ||
const groups: GroupedDiscounts = {}; | ||
|
||
for (let discount of discounts) { | ||
groups[discount.kind] = groups[discount.kind] ?? []; | ||
groups[discount.kind]?.push(discount); | ||
} | ||
|
||
return groups; | ||
} | ||
|
||
const groupedDiscounts = groupDiscounts(discounts); | ||
|
||
console.log(groupedDiscounts); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "@total-typescript/tsconfig/tsc/no-dom/app" | ||
} |