Skip to content

Commit

Permalink
Section 2: Lab: Type Safe Creators
Browse files Browse the repository at this point in the history
  • Loading branch information
simonplend committed Jun 4, 2024
1 parent 650c9b3 commit 5602233
Show file tree
Hide file tree
Showing 4 changed files with 275 additions and 0 deletions.
8 changes: 8 additions & 0 deletions 02-improving-type-safety/lab/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Lab: Type Safe Creators

## Requirements

1. There are eight pesky type errors in the Step 1 section of `start.ts`. Use the `satisfies` operator to help you fix them.
2. In the `for...of` loop in Step 2 section, `Array.isArray` is used to narrow the type for the `creator` variable. Refactor this code to use type predicates to narrow the type instead.
1. Create two type predicate functions: `isDirector()` and `isProducer()`
2. Hint: The return type for these functions should be a type predicate where the type is an intersection type.
136 changes: 136 additions & 0 deletions 02-improving-type-safety/lab/solution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
interface Creator {
firstName: string;
lastName: string;
authored?: string[];
created?: string[];
directed?: string[];
produced?: string[];
}

// ---- STEP 1 ----

console.log("\n>>>> STEP 1 <<<<\n");

const authors = [
{
firstName: "Harper",
lastName: "Lee",
authored: ["To Kill a Mockingbird", "Go Set a Watchman"],
},
{
firstName: "Aldous",
lastName: "Huxley",
authored: ["Brave New World", "The Doors of Perception"],
},
] satisfies Creator[];

const artists = [
{
firstName: "Pink",
lastName: "Floyd",
created: ["The Dark Side of the Moon", "The Wall"],
},
{
firstName: "Snoop",
lastName: "Dogg",
created: ["Tha Doggfather", "Coolaid"],
},
] satisfies Creator[];

const directors = [
{
firstName: "Christopher",
lastName: "Nolan",
directed: ["Inception", "Interstellar"],
},
{
firstName: "Stanley",
lastName: "Kubrick",
directed: ["2001: A Space Odyssey", "A Clockwork Orange"],
},
] satisfies Creator[];

const producers = [
{
firstName: "Emma",
lastName: "Thomas",
produced: ["Inception", "Interstellar"],
},
{
firstName: "Katharina",
lastName: "Otto-Bernstein",
produced: ["Absolute Wilson", "Beuys"],
},
] satisfies Creator[];

const creators = {
authors,
artists,
directors,
producers,
} satisfies Record<string, Creator[]>;

for (let creator of creators.authors) {
console.log(
`${creator.firstName} ${
creator.lastName
} is an author who wrote the books ${creator.authored.join(", ")}`
);
}

for (let creator of creators.artists) {
console.log(
`${creator.firstName} ${
creator.lastName
} is an artist who created the albums ${creator.created.join(", ")}`
);
}

for (let creator of creators.directors) {
console.log(
`${creator.firstName} ${
creator.lastName
} is a director who directed the movies ${creator.directed.join(", ")}`
);
}

for (let creator of creators.producers) {
console.log(
`${creator.firstName} ${
creator.lastName
} is a producer who produced the movies ${creator.produced.join(", ")}`
);
}

// ---- STEP 2 ----

console.log("\n>>>> STEP 2 <<<<\n");

function isDirector(creator: Creator): creator is Creator & { directed: string[] } {
return creator.directed !== undefined;
}

function isProducer(creator: Creator): creator is Creator & { produced: string[] } {
return creator.produced !== undefined;
}

const filmCreators: Creator[] = [...directors, ...producers];

for (let creator of filmCreators) {
let creatorType = "<unknown>";
let created: string[] = [];

if (isDirector(creator)) {
creatorType = "director";
created = creator.directed;
} else if (isProducer(creator)) {
creatorType = "producer";
created = creator.produced;
}

console.log(
`${creator.firstName} ${
creator.lastName
} is a ${creatorType} who helped create ${created.join(", ")}`
);
}
128 changes: 128 additions & 0 deletions 02-improving-type-safety/lab/start.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
interface Creator {
firstName: string;
lastName: string;
authored?: string[];
created?: string[];
directed?: string[];
produced?: string[];
}

// ---- STEP 1 ----

console.log("\n>>>> STEP 1 <<<<\n");

const authors: Creator[] = [
{
firstName: "Harper",
lastName: "Lee",
authored: ["To Kill a Mockingbird", "Go Set a Watchman"],
},
{
firstName: "Aldous",
lastName: "Huxley",
authored: ["Brave New World", "The Doors of Perception"],
},
];

const artists: Creator[] = [
{
firstName: "Pink",
lastName: "Floyd",
created: ["The Dark Side of the Moon", "The Wall"],
},
{
firstName: "Snoop",
lastName: "Dogg",
created: ["Tha Doggfather", "Coolaid"],
},
];

const directors: Creator[] = [
{
firstName: "Christopher",
lastName: "Nolan",
directed: ["Inception", "Interstellar"],
},
{
firstName: "Stanley",
lastName: "Kubrick",
directed: ["2001: A Space Odyssey", "A Clockwork Orange"],
},
];

const producers: Creator[] = [
{
firstName: "Emma",
lastName: "Thomas",
produced: ["Inception", "Interstellar"],
},
{
firstName: "Katharina",
lastName: "Otto-Bernstein",
produced: ["Absolute Wilson", "Beuys"],
},
];

const creators: Record<string, Creator[]> = {
authors,
artists,
directors,
producers,
};

for (let creator of creators.authors) {
console.log(
`${creator.firstName} ${
creator.lastName
} is an author who wrote the books ${creator.authored.join(", ")}`
);
}

for (let creator of creators.artists) {
console.log(
`${creator.firstName} ${
creator.lastName
} is an artist who created the albums ${creator.created.join(", ")}`
);
}

for (let creator of creators.directors) {
console.log(
`${creator.firstName} ${
creator.lastName
} is a director who directed the movies ${creator.directed.join(", ")}`
);
}

for (let creator of creators.producers) {
console.log(
`${creator.firstName} ${
creator.lastName
} is a producer who produced the movies ${creator.produced.join(", ")}`
);
}

// ---- STEP 2 ----

console.log("\n>>>> STEP 2 <<<<\n");

const filmCreators: Creator[] = [...directors, ...producers];

for (let creator of filmCreators) {
let creatorType = "<unknown>";
let created: string[] = [];

if (Array.isArray(creator.directed)) {
creatorType = "director";
created = creator.directed;
} else if (Array.isArray(creator.produced)) {
creatorType = "producer";
created = creator.produced;
}

console.log(
`${creator.firstName} ${
creator.lastName
} is a ${creatorType} who helped create ${created.join(", ")}`
);
}
3 changes: 3 additions & 0 deletions 02-improving-type-safety/lab/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "@total-typescript/tsconfig/tsc/no-dom/app"
}

0 comments on commit 5602233

Please sign in to comment.