diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index 860f1d5563a..54135d27993 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -6187,6 +6187,12 @@ "In this workshop, you will practice working with type annotations, array types, object types and more by building out a user profile." ] }, + "workshop-type-safe-math-toolkit": { + "title": "Build a Type Safe Math Toolkit", + "intro": [ + "In this workshop, you will practice typing functions by building a math toolkit project." + ] + }, "lecture-understanding-type-composition": { "title": "Understanding Type Composition", "intro": [ diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f1d72e906e4616155290d.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f1d72e906e4616155290d.md new file mode 100644 index 00000000000..567b9a526a8 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f1d72e906e4616155290d.md @@ -0,0 +1,53 @@ +--- +id: 699f1d72e906e4616155290d +title: Step 1 +challengeType: 1 +dashedName: step-1 +--- + +# --description-- + +In this workshop, you will continue to learn about type annotations and how they work with functions by building out a type safe math toolkit. + +Start by creating a function called `square` that accepts a parameter and returns the square of a number. + +# --hints-- + +You should have a function called `square`. + +```js +const explorer = await __helpers.Explorer(code); +assert.exists(explorer.allFunctions.square); +``` + +Your `square` function should have one parameter. + +```js +const explorer = await __helpers.Explorer(code); +assert.lengthOf(explorer.allFunctions.square.parameters, 1); +``` + +Your `square` function should return the square of a number. + +```js +assert.strictEqual(square(2), 4); +assert.strictEqual(square(3), 9); +``` + +# --seed-- + +## --seed-contents-- + +```ts +--fcc-editable-region-- + +--fcc-editable-region-- +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3738921fb79a651ded56.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3738921fb79a651ded56.md new file mode 100644 index 00000000000..fa28e186a44 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3738921fb79a651ded56.md @@ -0,0 +1,69 @@ +--- +id: 699f3738921fb79a651ded56 +title: Step 2 +challengeType: 1 +dashedName: step-2 +--- + +# --description-- + +Now it is time to call your function. + +Create a variable called `result` and assign it the function call of `square` with an argument of `5`. + +Below that, log the value of `result` to the console. + +# --before-each-- + +```js +const spy = __helpers.spyOn(console, 'log'); +const getLogs = () => spy.calls.map(call => call?.[0]); +``` + +# --hints-- + +You should have a variable called `result`. + +```js +assert.isDefined(result); +``` + +Your `result` variable should be a number. + +```js +assert.isNumber(result); +``` + +Your `result` variable should be the square of `5`. + +```js +assert.strictEqual(result, 25); +``` + +You should log the `result` variable to the console. + +```js +assert.equal(getLogs()[0], result); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num) { + return num * num; +} + +--fcc-editable-region-- + +--fcc-editable-region-- +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f38937b053e4679878ff1.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f38937b053e4679878ff1.md new file mode 100644 index 00000000000..e175fa12b34 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f38937b053e4679878ff1.md @@ -0,0 +1,47 @@ +--- +id: 699f38937b053e4679878ff1 +title: Step 3 +challengeType: 1 +dashedName: step-3 +--- + +# --description-- + +When working with vanilla JavaScript, there is nothing to prevent you from calling the `square` function with a string or an array, which would lead to unexpected results. + +To illustrate this, change your function call to use the string `"something"` instead of the number `5`. + +In the next lesson, you will learn how to use TypeScript to add type safety to your code and prevent these kinds of errors. + +# --hints-- + +Your `square` function call should have an argument of `"something"`. + +```js +const explorer = await __helpers.Explorer(code); +assert.isTrue(explorer.variables.result.value.matches("square('something')")); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num) { + return num * num; +} + +--fcc-editable-region-- +const result = square(5); +--fcc-editable-region-- + +console.log(result); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3cb8d057f29954205d7d.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3cb8d057f29954205d7d.md new file mode 100644 index 00000000000..cb71a198412 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3cb8d057f29954205d7d.md @@ -0,0 +1,74 @@ +--- +id: 699f3cb8d057f29954205d7d +title: Step 4 +challengeType: 1 +dashedName: step-4 +--- + +# --description-- + +As you recall from earlier lessons, you can add type annotations to function parameters like this: + +```ts +function add(num1: number, num2: number) { + return num1 + num2; +} +``` + +In this example, TypeScript will display an error if you try to call the `add` function with arguments that are not numbers. + +Update your `square` function to include a type annotation for the `num` parameter. The type should be `number`. + +# --hints-- + +You should add a type annotation to the `num` parameter in the `square` function. The type should be a `number`. + +```js +const explorer = await __helpers.Explorer(code); +const { parameters } = explorer.allFunctions.square; +assert.isTrue(parameters[0].matches("num: number")); +``` + +# --seed-- + +## --seed-contents-- + +```ts +--fcc-editable-region-- +function square(num) { + return num * num; +} + +--fcc-editable-region-- +const result = square("something"); + +console.log(result); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` + +# --solutions-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square("something"); + +console.log(result); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3f636aa840b7201aa37c.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3f636aa840b7201aa37c.md new file mode 100644 index 00000000000..ca54280a1f0 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f3f636aa840b7201aa37c.md @@ -0,0 +1,43 @@ +--- +id: 699f3f636aa840b7201aa37c +title: Step 5 +challengeType: 1 +dashedName: step-5 +--- + +# --description-- + +If you open up the console, you should see the following TypeScript error message: + +```md +Argument of type 'string' is not assignable to parameter of type 'number' +``` + +Now that the parameter is explicitly typed as a number, TypeScript is able to catch the error of trying to pass a string argument to the `square` function. + +Change the argument passed to the `square` function to the number `5` to fix the error and see the correct output in the console. + +# --hints-- + +Your `square` function call should have an argument of `5` instead of `"something"`. + +```js +assert.strictEqual(result, 25); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +--fcc-editable-region-- +const result = square("something"); +--fcc-editable-region-- + +console.log(result); +``` + diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f412114c87221f16a99e3.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f412114c87221f16a99e3.md new file mode 100644 index 00000000000..6d658702dd9 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f412114c87221f16a99e3.md @@ -0,0 +1,66 @@ +--- +id: 699f412114c87221f16a99e3 +title: Step 6 +challengeType: 1 +dashedName: step-6 +--- + +# --description-- + +Another benefit of using TypeScript is that it will catch errors if you pass to many or to few arguments to a function call. + +To illustrate this, update your `square` function call to take two arguments of `5` and `10`. + +# --hints-- + +Your `square` function call should have two arguments of `5` and `10`. + +```js +const explorer = await __helpers.Explorer(code); +const { result } = explorer.variables; +assert.isTrue(result.value.matches("square(5, 10)")); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +--fcc-editable-region-- +const result = square(5); +--fcc-editable-region-- + +console.log(result); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` + +# --solutions-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5, 10); + +console.log(result); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f41b8da20f816b5c7dece.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f41b8da20f816b5c7dece.md new file mode 100644 index 00000000000..17a843f6041 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f41b8da20f816b5c7dece.md @@ -0,0 +1,41 @@ +--- +id: 699f41b8da20f816b5c7dece +title: Step 7 +challengeType: 1 +dashedName: step-7 +--- + +# --description-- + +If you open up the console, you should see the following error message: + +```md +Expected 1 arguments, but got 2. +``` + +To resolve the error, update your `square` function call to take only one argument of `5`. + +# --hints-- + +Your `square` function call should have only one argument of `5`. + +```js +assert.strictEqual(result, 25); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +--fcc-editable-region-- +const result = square(5, 10); +--fcc-editable-region-- + +console.log(result); +``` + diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f434e294a9e11cf4f65f0.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f434e294a9e11cf4f65f0.md new file mode 100644 index 00000000000..99808f82dc7 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f434e294a9e11cf4f65f0.md @@ -0,0 +1,68 @@ +--- +id: 699f434e294a9e11cf4f65f0 +title: Step 8 +challengeType: 1 +dashedName: step-8 +--- + +# --description-- + +Now it is time to add another math helper to your toolkit project. + +Start by creating a function called `getAverage` which takes one parameter. Your function should return the average for an array of numbers. + +In the next few steps, you will add the type annotations for this function. + +# --hints-- + +You should have a function called `getAverage`. + +```js +assert.isFunction(getAverage); +``` + +Your function should take one parameter. + +```js +assert.strictEqual(getAverage.length, 1); +``` + +Your function should return a number. + +```js +assert.isNumber(getAverage([1, 2, 3])); +``` + +Your function should return the correct result for any array of numbers. + +```js +assert.strictEqual(getAverage([1, 2, 3, 4, 5]), 3); +assert.strictEqual(getAverage([10, 20, 30]), 20); +assert.strictEqual(getAverage([5, 10, 15, 20]), 12.5); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +--fcc-editable-region-- + +--fcc-editable-region-- +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f458e47fb88c756fdba81.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f458e47fb88c756fdba81.md new file mode 100644 index 00000000000..393fced8554 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f458e47fb88c756fdba81.md @@ -0,0 +1,57 @@ +--- +id: 699f458e47fb88c756fdba81 +title: Step 9 +challengeType: 1 +dashedName: step-9 +--- + +# --description-- + +Right now, the `numbers` parameter has an implicit `any` type. To fix this, you can explicitly type the parameter as an array of numbers. + +Recall from prior lessons, that you can type an array of numbers like this: + +```ts +const numbers: number[] = [1, 2, 3]; +``` + +Update your `getAverage` function to explicitly type the `numbers` parameter as an array of numbers. + +# --hints-- + +Your `getAverage` function should have a parameter named `numbers` that is explicitly typed as an array of numbers. + +```js +const explorer = await __helpers.Explorer(code); +const parameters = explorer.allFunctions.getAverage.parameters; +assert.isTrue(parameters[0].matches("numbers: number[]")); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +--fcc-editable-region-- +function getAverage(numbers) { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} +--fcc-editable-region-- +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4639ae0016caaf81b7c6.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4639ae0016caaf81b7c6.md new file mode 100644 index 00000000000..763cee8f031 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4639ae0016caaf81b7c6.md @@ -0,0 +1,78 @@ +--- +id: 699f4639ae0016caaf81b7c6 +title: Step 10 +challengeType: 1 +dashedName: step-10 +--- + +# --description-- + +Now it is time to test out your function. + +Start by creating a variable called `avgResult` and assigning it the function call of `getAverage`. The argument for that function call should be `[2, 14, 26, 8]`. + +Then log the value of `avgResult` to the console. + +# --before-each-- + +```js +const spy = __helpers.spyOn(console, 'log'); +const getLogs = () => spy.calls.map(call => call?.[0]); +``` + +# --hints-- + +You should have a variable called `avgResult`. + +```js +assert.isDefined(avgResult); +``` + +You should assign `getAverage([2, 14, 26, 8])` to your `avgResult` variable. + +```js +assert.strictEqual(avgResult, getAverage([2, 14, 26, 8])); +``` + +Your `avgResult` variable should be a number. + +```js +assert.isNumber(avgResult); +``` + +You should log `avgResult` to the console. + +```js +assert.equal(getLogs()[1], avgResult); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]) { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} + +--fcc-editable-region-- + +--fcc-editable-region-- +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4861dd5b5f164e1bda4a.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4861dd5b5f164e1bda4a.md new file mode 100644 index 00000000000..58549d0365b --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4861dd5b5f164e1bda4a.md @@ -0,0 +1,59 @@ +--- +id: 699f4861dd5b5f164e1bda4a +title: Step 11 +challengeType: 1 +dashedName: step-11 +--- + +# --description-- + +Another benefit of using TypeScript is ensuring that the return types are enforced and what you expect. Sometimes TypeScript can infer the return type of a function, but you can also explicitly specify it. + +To illustrate this, change the return type of the `getAverage` function to the string `"something"`. + +# --hints-- + +Your `getAverage` function should return a string. + +```js +assert.isString(getAverage([2, 14, 26, 8])); +``` + +Your `getAverage` function should return the string `"something"`. + +```js +assert.strictEqual(getAverage([2, 14, 26, 8]), "something"); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]) { + const sum = numbers.reduce((acc, n) => acc + n, 0); + --fcc-editable-region-- + return sum / numbers.length; + --fcc-editable-region-- +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f49669ea51a31d2ba89d8.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f49669ea51a31d2ba89d8.md new file mode 100644 index 00000000000..d1d3ef53a01 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f49669ea51a31d2ba89d8.md @@ -0,0 +1,92 @@ +--- +id: 699f49669ea51a31d2ba89d8 +title: Step 12 +challengeType: 1 +dashedName: step-12 +--- + +# --description-- + +As you recall from prior lessons, you can explicitly type the return type for a function like this: + +```ts +function circleArea(radius: number): number { + return Math.PI * radius * radius; +} +``` + +In this example, the return type of the `circleArea` function is `number`. If you try to return a different type, TypeScript will display an error. + +Update your `getAverage` function to explicitly type the return type as `number`. + +# --hints-- + +Your `getAverage` function should have a return type of `number`. + +```js +const explorer = await __helpers.Explorer(code); +const { getAverage } = explorer.allFunctions; +assert.isTrue(getAverage.hasReturnAnnotation("number")); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +--fcc-editable-region-- +function getAverage(numbers: number[]) { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return "something"; +} +--fcc-editable-region-- + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` + +# --solutions-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return "something"; +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4a3e7b4c6bfa538cc4f7.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4a3e7b4c6bfa538cc4f7.md new file mode 100644 index 00000000000..c16294b5098 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4a3e7b4c6bfa538cc4f7.md @@ -0,0 +1,58 @@ +--- +id: 699f4a3e7b4c6bfa538cc4f7 +title: Step 13 +challengeType: 1 +dashedName: step-13 +--- + +# --description-- + +If you open up the console, you will see the following error message: + +```md +Type 'string' is not assignable to type 'number'. +``` + +To resolve this error, you need to change the return back to `sum / numbers.length`. + +# --hints-- + +Your `getAverage` function should return a number. + +```js +assert.isNumber(getAverage([1, 2, 3])); +``` + +Your `getAverage` function should return the average of the numbers in the array. + +```js +assert.strictEqual(getAverage([1, 2, 3]), 2); +assert.strictEqual(getAverage([10, 20, 30]), 20); +assert.strictEqual(getAverage([5, 10, 15, 20]), 12.5); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +--fcc-editable-region-- +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return "something"; +} +--fcc-editable-region-- + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); +``` + diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4b903bf5427a599f791d.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4b903bf5427a599f791d.md new file mode 100644 index 00000000000..d1c75d9f61b --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4b903bf5427a599f791d.md @@ -0,0 +1,93 @@ +--- +id: 699f4b903bf5427a599f791d +title: Step 14 +challengeType: 1 +dashedName: step-14 +--- + +# --description-- + +In the last few steps, you will build out one more function to continue practicing type annotations with functions. + +Start by creating a function called `raiseTo` which take two parameters called `base` and `exponent`. Both parameters should be of type `number`. The function should return the result of raising the `base` to the power of the `exponent`. The return type of the function should also be annotated as `number`. + +# --hints-- + +You should have a `raiseTo` function. + +```js +assert.isFunction(raiseTo); +``` + +Your `raiseTo` function should have two parameters, `base` and `exponent`. + +```js +assert.match( + code, + /function\s+raiseTo\s*\(\s*base\s*(?::\s*number)?\s*,\s*exponent\s*(?::\s*number)?\s*\)\s*|(?:const|let)\s+raiseTo\s*=\s*\(\s*base\s*(?::\s*number)?\s*,\s*exponent\s*(?::\s*number)?\s*\)\s*=>/ +); +``` + +Your `base` and `exponent` parameters should both be of type `number`. + +```js +const explorer = await __helpers.Explorer(code); +const { parameters } = explorer.allFunctions.raiseTo; +assert.isTrue(parameters[0].matches("base: number")); +assert.isTrue(parameters[1].matches("exponent: number")); +``` + +Your `raiseTo` function should return a number. + +```js +assert.isNumber(raiseTo(2, 3)); +``` + +Your `raiseTo` function should return the result of raising the `base` to the power of the `exponent`. + +```js +assert.strictEqual(raiseTo(2, 3), 8); +``` + +Your `raiseTo` function should have a return type annotation of `number`. + +```js +const explorer = await __helpers.Explorer(code); +const { raiseTo } = explorer.allFunctions; +assert.isTrue(raiseTo.hasReturnAnnotation("number")); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); + +--fcc-editable-region-- + +--fcc-editable-region-- +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4ec939f10da62fb56c3e.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4ec939f10da62fb56c3e.md new file mode 100644 index 00000000000..cb321d41796 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f4ec939f10da62fb56c3e.md @@ -0,0 +1,80 @@ +--- +id: 699f4ec939f10da62fb56c3e +title: Step 15 +challengeType: 1 +dashedName: step-15 +--- + +# --description-- + +Now it is time to test out your function. + +Create a variable called `raisedResult` and assign it the result of calling `raiseTo` with the arguments `2` and `3`. + +Then, log `raisedResult` to the console. + +# --before-each-- + +```js +const spy = __helpers.spyOn(console, 'log'); +const getLogs = () => spy.calls.map(call => call?.[0]); +``` + +# --hints-- + +You should have a variable called `raisedResult`. + +```js +assert.isDefined(raisedResult); +``` + +Your `raisedResult` variable should be a number. + +```js +assert.isNumber(raisedResult); +``` + +You should log `raisedResult` to the console. + +```js +assert.equal(getLogs()[2], raisedResult); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); + +function raiseTo(base: number, exponent: number): number { + return base ** exponent; +} + +--fcc-editable-region-- + +--fcc-editable-region-- +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f5063d2393c674b1f45dc.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f5063d2393c674b1f45dc.md new file mode 100644 index 00000000000..764548f7b7c --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f5063d2393c674b1f45dc.md @@ -0,0 +1,77 @@ +--- +id: 699f5063d2393c674b1f45dc +title: Step 16 +challengeType: 1 +dashedName: step-16 +--- + +# --description-- + +As you recall from a prior step, if you call a function with the wrong number of arguments, TypeScript will throw and error. + +There is a way to mark parameters as optional by adding a `?` after the parameter name. This allows you to call the function with fewer arguments than parameters. + +Here is an example: + +```ts +function greet(name: string, greeting?: string) { + if (greeting) { + return `${greeting}, ${name}!`; + } + return `Hello, ${name}!`; +} +``` + +In this example, if the `greeting` parameter is not provided when calling the `greet` function, it will be `undefined`, and the function will return a default greeting. + +Update your `raiseTo` function to make the `exponent` parameter optional. + +# --hints-- + +Your `raiseTo` function should have the `exponent` parameter marked as optional. + +```js +const explorer = await __helpers.Explorer(code); +const { parameters } = explorer.allFunctions.raiseTo; +assert.isTrue(parameters[1].matches("exponent?: number")); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); + +--fcc-editable-region-- +function raiseTo(base: number, exponent: number): number { + return base ** exponent; +} +--fcc-editable-region-- + +const raisedResult = raiseTo(2, 3); +console.log(raisedResult); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f513e01eb1768cc5df726.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f513e01eb1768cc5df726.md new file mode 100644 index 00000000000..54c7c842781 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f513e01eb1768cc5df726.md @@ -0,0 +1,63 @@ +--- +id: 699f513e01eb1768cc5df726 +title: Step 17 +challengeType: 1 +dashedName: step-17 +--- + +# --description-- + +Now that the `exponent` parameter is marked as optional, you can call the function with just one argument. + +Update your `raiseTo` function call to only pass in the number `3`. + +# --hints-- + +Your `raiseTo` function should be called with only one argument of `3`. + +```js +assert.match( + code, + /raiseTo\s*\(\s*3\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); + +function raiseTo(base: number, exponent?: number): number { + return base ** exponent; +} + +--fcc-editable-region-- +const raisedResult = raiseTo(2, 3); +--fcc-editable-region-- +console.log(raisedResult); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f52220de88c8091032076.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f52220de88c8091032076.md new file mode 100644 index 00000000000..540e3b0e23a --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f52220de88c8091032076.md @@ -0,0 +1,69 @@ +--- +id: 699f52220de88c8091032076 +title: Step 18 +challengeType: 1 +dashedName: step-18 +--- + +# --description-- + +If you open up the console, the result is `NaN` because the second argument for the `exponent` was never provided. There are a couple of updates needed for this `raiseTo` function that will fix this. + +The first change is to return `base ** 2`. + +In the next step, you will see how to handle the optional `exponent` parameter. + +# --hints-- + +Your `raiseTo` function should return a number. + +```js +assert.isNumber(raiseTo(4)); +``` + +Your `raiseTo` function should return the value of `base` raised to the power of `2`. + +```js +assert.strictEqual(raiseTo(4), 16); +assert.strictEqual(raiseTo(5), 25); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); + +--fcc-editable-region-- +function raiseTo(base: number, exponent?: number): number { + return base ** exponent; +} +--fcc-editable-region-- + +const raisedResult = raiseTo(3); +console.log(raisedResult); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f52fac083214b6bf51de6.md b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f52fac083214b6bf51de6.md new file mode 100644 index 00000000000..cf5ca37f68d --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-type-safe-math-toolkit/699f52fac083214b6bf51de6.md @@ -0,0 +1,109 @@ +--- +id: 699f52fac083214b6bf51de6 +title: Step 19 +challengeType: 1 +dashedName: step-19 +--- + +# --description-- + +In this last step, you will need to add a conditional check for the `exponent` parameter in the `raiseTo` function. + +If the `exponent` argument is provided, the function should return `base` raised to the power of `exponent`. If the `exponent` argument is not provided, it should return `base ** 2`. + +With that last step, your type-safe math toolkit is complete! + +# --hints-- + +Your `raiseTo` function should return `base ** exponent` when `exponent` argument is provided. + +```js +assert.strictEqual(raiseTo(3, 3), 27); +``` + +Your `raiseTo` function should return `base ** 2` when `exponent` argument is not provided. + +```js +assert.strictEqual(raiseTo(3), 9); +``` + +# --seed-- + +## --seed-contents-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); + +--fcc-editable-region-- +function raiseTo(base: number, exponent?: number): number { + + return base ** 2; +} +--fcc-editable-region-- + +const raisedResult = raiseTo(3); +console.log(raisedResult); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` + +# --solutions-- + +```ts +function square(num: number) { + return num * num; +} + +const result = square(5); + +console.log(result); + +function getAverage(numbers: number[]): number { + const sum = numbers.reduce((acc, n) => acc + n, 0); + return sum / numbers.length; +} + +const avgResult = getAverage([2, 14, 26, 8]); + +console.log(avgResult); + +function raiseTo(base: number, exponent?: number): number { + if (exponent) { + return base ** exponent; + } + + return base ** 2; +} + +const raisedResult = raiseTo(3); +console.log(raisedResult); +``` + +```json +{ + "compilerOptions": { + "noCheck": true + } +} +``` diff --git a/curriculum/structure/blocks/workshop-type-safe-math-toolkit.json b/curriculum/structure/blocks/workshop-type-safe-math-toolkit.json new file mode 100644 index 00000000000..c8389ab7bf7 --- /dev/null +++ b/curriculum/structure/blocks/workshop-type-safe-math-toolkit.json @@ -0,0 +1,30 @@ +{ + "isUpcomingChange": true, + "dashedName": "workshop-type-safe-math-toolkit", + "helpCategory": "JavaScript", + "blockLayout": "challenge-grid", + "challengeOrder": [ + { "id": "699f1d72e906e4616155290d", "title": "Step 1" }, + { "id": "699f3738921fb79a651ded56", "title": "Step 2" }, + { "id": "699f38937b053e4679878ff1", "title": "Step 3" }, + { "id": "699f3cb8d057f29954205d7d", "title": "Step 4" }, + { "id": "699f3f636aa840b7201aa37c", "title": "Step 5" }, + { "id": "699f412114c87221f16a99e3", "title": "Step 6" }, + { "id": "699f41b8da20f816b5c7dece", "title": "Step 7" }, + { "id": "699f434e294a9e11cf4f65f0", "title": "Step 8" }, + { "id": "699f458e47fb88c756fdba81", "title": "Step 9" }, + { "id": "699f4639ae0016caaf81b7c6", "title": "Step 10" }, + { "id": "699f4861dd5b5f164e1bda4a", "title": "Step 11" }, + { "id": "699f49669ea51a31d2ba89d8", "title": "Step 12" }, + { "id": "699f4a3e7b4c6bfa538cc4f7", "title": "Step 13" }, + { "id": "699f4b903bf5427a599f791d", "title": "Step 14" }, + { "id": "699f4ec939f10da62fb56c3e", "title": "Step 15" }, + { "id": "699f5063d2393c674b1f45dc", "title": "Step 16" }, + { "id": "699f513e01eb1768cc5df726", "title": "Step 17" }, + { "id": "699f52220de88c8091032076", "title": "Step 18" }, + { "id": "699f52fac083214b6bf51de6", "title": "Step 19" } + ], + "blockLabel": "workshop", + "usesMultifileEditor": true, + "hasEditableBoundaries": true +} diff --git a/curriculum/structure/superblocks/front-end-development-libraries-v9.json b/curriculum/structure/superblocks/front-end-development-libraries-v9.json index 20793aec875..51cee03b4db 100644 --- a/curriculum/structure/superblocks/front-end-development-libraries-v9.json +++ b/curriculum/structure/superblocks/front-end-development-libraries-v9.json @@ -92,6 +92,7 @@ "blocks": [ "lecture-introduction-to-typescript", "workshop-type-safe-user-profile", + "workshop-type-safe-math-toolkit", "lecture-understanding-type-composition", "lecture-working-with-generics-and-type-narrowing", "lecture-working-with-typescript-configuration-files",