-
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.
Section 2: Exercise: Library for a Library
- Loading branch information
1 parent
a709221
commit 650c9b3
Showing
9 changed files
with
220 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,6 @@ | ||
# Exercise: Library for a Library | ||
|
||
In this exercise, we'll be creating a library with the following functions: | ||
|
||
- `describeItem(item: LibraryItem): void` | ||
- `getMovieById(id: Movie['id']): Promise<string>` |
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,68 @@ | ||
import { type Brand } from './utils.js'; | ||
|
||
export interface Book { | ||
type: 'book', | ||
id: string; | ||
title: string; | ||
published: number; | ||
author: string; | ||
} | ||
|
||
export interface Album { | ||
type: 'album', | ||
id: string; | ||
title: string; | ||
released: number; | ||
artist: string; | ||
} | ||
|
||
export interface MotionPicture { | ||
id: unknown; | ||
title: string; | ||
released: number; | ||
director: string; | ||
} | ||
|
||
export interface Movie extends MotionPicture { | ||
type: 'movie', | ||
id: Brand<string, 'MovieId'>; | ||
} | ||
|
||
export interface Show extends MotionPicture { | ||
type: 'show', | ||
id: Brand<string, 'ShowId'>; | ||
} | ||
|
||
export type LibraryItem = Book | Album | Movie | Show; | ||
|
||
export const book: Book = { | ||
type: 'book', | ||
id: '82f7c297-40ec-4e9f-90b0-a12f2b4980c1', | ||
title: 'To Kill a Mockingbird', | ||
published: 1960, | ||
author: 'Harper Lee' | ||
} | ||
|
||
export const album: Album = { | ||
type: 'album', | ||
id: '1dc8dd44-245e-4a5f-b1b6-8c02fd2a9dc1', | ||
title: 'The Dark Side of the Moon', | ||
released: 1973, | ||
artist: 'Pink Floyd' | ||
}; | ||
|
||
export const movie: Movie = { | ||
type: 'movie', | ||
id: 'f928756a-d3d9-4db3-92ea-88100d03af47' as Movie['id'], | ||
title: 'Point Break', | ||
released: 1991, | ||
director: 'Kathryn Bigelow' | ||
}; | ||
|
||
export const show: Show = { | ||
type: 'show', | ||
id: 'c9a7b229-b48f-4407-a267-45ff7fe8ea60' as Show['id'], | ||
title: 'Westworld', | ||
released: 2016, | ||
director: 'Jonathan Nolan' | ||
}; |
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,80 @@ | ||
import { | ||
book, | ||
album, | ||
movie, | ||
show, | ||
type Book, | ||
type Album, | ||
type Movie, | ||
type Show, | ||
type LibraryItem, | ||
} from "./data.js"; | ||
|
||
import { fetchApiData } from "./utils.js"; | ||
|
||
function isBook(item: LibraryItem): item is Book { | ||
return item.type === "book"; | ||
} | ||
|
||
function isAlbum(item: LibraryItem): item is Album { | ||
return item.type === "album"; | ||
} | ||
|
||
function isMovie(item: LibraryItem): item is Movie { | ||
return item.type === "movie"; | ||
} | ||
|
||
function isShow(item: LibraryItem): item is Show { | ||
return item.type === "show"; | ||
} | ||
|
||
function describeLibraryItem(item: LibraryItem) { | ||
if (isBook(item)) { | ||
console.log( | ||
`- ${item.title} is a book written by ${item.author}, and published in ${item.published}.` | ||
); | ||
} else if (isAlbum(item)) { | ||
console.log( | ||
`- ${item.title} is an album by the artist ${item.artist}, released in ${item.released}` | ||
); | ||
} else if (isMovie(item)) { | ||
console.log( | ||
`- ${item.title} is a movie directed by ${item.director}, released in ${item.released}` | ||
); | ||
} else if (isShow(item)) { | ||
console.log( | ||
`- ${item.title} is a show directed by ${item.director}, released in ${item.released}` | ||
); | ||
} else { | ||
console.error("Error: Unrecognised library item!"); | ||
} | ||
} | ||
|
||
describeLibraryItem(book); | ||
describeLibraryItem(album); | ||
describeLibraryItem(movie); | ||
describeLibraryItem(show); | ||
|
||
function assertIsMovie(item: LibraryItem): asserts item is Movie { | ||
if (item.type !== 'movie') { | ||
throw new Error(`This item is not a Movie: ${item.title}`); | ||
} | ||
} | ||
|
||
async function getMovieById(id: Movie['id']) { | ||
const apiData = await fetchApiData(); | ||
|
||
const movie = apiData.find((item: LibraryItem) => item.id === id); | ||
|
||
if (!movie) { | ||
throw new Error('Movie not found'); | ||
} | ||
|
||
assertIsMovie(movie); | ||
|
||
return movie; | ||
} | ||
|
||
const movieDetails = await getMovieById(movie.id); | ||
|
||
console.log(movieDetails); |
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,13 @@ | ||
import { movie, show, book, album } from "./data.js"; | ||
|
||
export async function fetchApiData() { | ||
const data = [movie, show, book, album]; | ||
const apiResponse = structuredClone(data); | ||
return apiResponse; | ||
} | ||
|
||
declare const __brand: unique symbol; | ||
|
||
export type Brand<BaseType, BrandedName extends string> = BaseType & { | ||
[__brand]: BrandedName; | ||
}; |
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,31 @@ | ||
export const book = { | ||
type: 'book', | ||
id: '82f7c297-40ec-4e9f-90b0-a12f2b4980c1', | ||
title: 'To Kill a Mockingbird', | ||
published: 1960, | ||
author: 'Harper Lee' | ||
} | ||
|
||
export const album = { | ||
type: 'album', | ||
id: '1dc8dd44-245e-4a5f-b1b6-8c02fd2a9dc1', | ||
title: 'The Dark Side of the Moon', | ||
released: 1973, | ||
artist: 'Pink Floyd' | ||
}; | ||
|
||
export const movie = { | ||
type: 'movie', | ||
id: 'f928756a-d3d9-4db3-92ea-88100d03af47', | ||
title: 'Point Break', | ||
released: 1991, | ||
director: 'Kathryn Bigelow' | ||
}; | ||
|
||
export const show = { | ||
type: 'show', | ||
id: 'c9a7b229-b48f-4407-a267-45ff7fe8ea60', | ||
title: 'Westworld', | ||
released: 2016, | ||
director: 'Jonathan Nolan' | ||
}; |
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 @@ | ||
import { book, album, movie, show } from "./data.js"; | ||
|
||
import { fetchApiData } from "./utils.js"; |
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,13 @@ | ||
import { movie, show, book, album } from "./data.js"; | ||
|
||
export async function fetchApiData() { | ||
const data = [movie, show, book, album]; | ||
const apiResponse = structuredClone(data); | ||
return apiResponse; | ||
} | ||
|
||
declare const __brand: unique symbol; | ||
|
||
export type Brand<BaseType, BrandedName extends string> = BaseType & { | ||
[__brand]: BrandedName; | ||
}; |