Skip to content

Commit 933ebcc

Browse files
committed
9.15
1 parent 1753c6e commit 933ebcc

5 files changed

Lines changed: 115 additions & 11 deletions

File tree

part9/courseinfo-ts/src/App.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,41 @@ import React from "react";
22
import Content from "./components/Content";
33
import Header from "./components/Header";
44
import Total from "./components/Total";
5+
import { CoursePart } from "./types";
56
const App = () => {
67
const courseName = "Half Stack application development";
7-
const courseParts = [
8+
const courseParts: CoursePart[] = [
89
{
910
name: "Fundamentals",
1011
exerciseCount: 10,
12+
description: "This is the leisured course part",
13+
type: "normal",
14+
},
15+
{
16+
name: "Advanced",
17+
exerciseCount: 7,
18+
description: "This is the harded course part",
19+
type: "normal",
1120
},
1221
{
1322
name: "Using props to pass data",
1423
exerciseCount: 7,
24+
groupProjectCount: 3,
25+
type: "groupProject",
1526
},
1627
{
1728
name: "Deeper type usage",
1829
exerciseCount: 14,
30+
description: "Confusing description",
31+
exerciseSubmissionLink: "https://fake-exercise-submit.made-up-url.dev",
32+
type: "submission",
33+
},
34+
{
35+
name: "Backend development",
36+
exerciseCount: 21,
37+
description: "Typing the backend",
38+
requirements: ["nodejs", "jest"],
39+
type: "special",
1940
},
2041
];
2142

part9/courseinfo-ts/src/components/Content.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import React from "react";
2-
import { ContentProps } from "../types";
2+
import { CoursePart } from "../types";
3+
import Part from "./Part";
34

4-
const Content = ({ courseParts }: ContentProps) => {
5+
const Content = ({ courseParts }: { courseParts: CoursePart[] }) => {
56
return (
67
<>
78
{courseParts.map((coursePart) => (
89
<p key={coursePart.name}>
9-
{coursePart.name} {coursePart.exerciseCount}
10+
<b>
11+
{coursePart.name} {coursePart.exerciseCount}
12+
</b>
13+
<Part coursePart={coursePart} />
1014
</p>
1115
))}
1216
</>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from "react";
2+
import { CoursePart } from "../types";
3+
4+
/**
5+
* Helper function for exhaustive type checking
6+
*/
7+
const assertNever = (value: never): never => {
8+
throw new Error(
9+
`Unhandled discriminated union member: ${JSON.stringify(value)}`
10+
);
11+
};
12+
13+
const Part = ({ coursePart }: { coursePart: CoursePart }) => {
14+
const render = (part: CoursePart) => {
15+
switch (part.type) {
16+
case "normal":
17+
return (
18+
<p>
19+
<i>{part.description} </i>
20+
</p>
21+
);
22+
case "groupProject":
23+
return <p> project exercises {part.groupProjectCount}</p>;
24+
case "submission":
25+
return (
26+
<p>
27+
<i>{part.description} </i>
28+
<p>submit to {part.exerciseSubmissionLink}</p>
29+
</p>
30+
);
31+
case "special":
32+
return (
33+
<p>
34+
<i>{part.description} </i>
35+
<p>
36+
skills
37+
{part.requirements.map((req) => (
38+
<ul>
39+
<li>{req}</li>
40+
</ul>
41+
))}
42+
</p>
43+
</p>
44+
);
45+
default:
46+
assertNever(part);
47+
}
48+
};
49+
return <div>{render(coursePart)}</div>;
50+
};
51+
52+
export default Part;

part9/courseinfo-ts/src/components/Total.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
2-
import { ContentProps } from "../types";
2+
import { CoursePart } from "../types";
33

4-
const Total = ({ courseParts }: ContentProps) => {
4+
const Total = ({ courseParts }: { courseParts: CoursePart[] }) => {
55
return (
66
<>
77
<p>

part9/courseinfo-ts/src/types.ts

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
1-
export interface ContentProps {
2-
courseParts: {
3-
name: string;
4-
exerciseCount: number;
5-
}[];
1+
interface CoursePartBase {
2+
name: string;
3+
exerciseCount: number;
4+
type: string;
65
}
6+
7+
interface CoursePartDesc extends CoursePartBase {
8+
description: string;
9+
}
10+
11+
interface CourseNormalPart extends CoursePartDesc {
12+
type: "normal";
13+
}
14+
interface CourseProjectPart extends CoursePartBase {
15+
type: "groupProject";
16+
groupProjectCount: number;
17+
}
18+
19+
interface CourseSubmissionPart extends CoursePartDesc {
20+
type: "submission";
21+
exerciseSubmissionLink: string;
22+
}
23+
24+
interface CoursePartRequirement extends CoursePartDesc {
25+
requirements: string[];
26+
type: "special";
27+
}
28+
29+
export type CoursePart =
30+
| CourseNormalPart
31+
| CourseProjectPart
32+
| CourseSubmissionPart
33+
| CoursePartRequirement;

0 commit comments

Comments
 (0)