Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notes for Intermediate TS v2 #936

Merged
merged 3 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions packages/notes-intermediate-ts-v2/src/10-covariance-contravariance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
class Snack {
constructor(public readonly petFriendly: boolean) {}
}
class Pretzel extends Snack {
constructor(public readonly salted = true) {
super(!salted)
}
}
class Cookie extends Snack {
public readonly petFriendly: false = false
constructor(
Expand All @@ -12,5 +17,173 @@ class Cookie extends Snack {
}
}

//* Covariance
/*
// interface Producer<T> {
// produce: () => T
// }

// let cookieProducer: Producer<Cookie> = {
// produce: () => new Cookie('dark'),
// }
// let snackProducer: Producer<Snack> = {
// produce: () => Math.random() > 0.5 ? new Cookie("milk") : new Pretzel(true)
// };

/*
// //? Type equivalence check
// snackProducer = cookieProducer //✔️ OK
// cookieProducer = snackProducer //! Nope

/*
// | Cookie | direction | Snack |
// |-----------------------|---------------|-----------------------|
// | `Cookie` | --- is a ---> | `Snack` |
// | `Producer<Cookie>` | --- is a ---> | `Producer<Snack>` |

/*
// interface Producer<out T> {
// produce: () => T
// }

//* Contravariance
/*
// interface Packager<T> {
// package: (item: T) => void
// }

// let cookiePackager: Packager<Cookie> = {
// package(item: Cookie) {},
// }

// let snackPackager: Packager<Snack> = {
// package(item: Snack) {
// if (item instanceof Cookie) {
// // Package cookie
// } else if (item instanceof Pretzel) {
// // Package pretzel
// } else {
// // Package other snacks?
// }
// },
// }

/*
// //? Type equivalence check
// cookiePackager = snackPackager //✔️ OK
// snackPackager = cookiePackager //! Nope

/*
// | Cookie | direction | Snack |
// |-----------------------|---------------|-----------------------|
// | `Cookie` | --- is a ---> | `Snack` |
// | `Packager<Cookie>` | <--- is a --- | `Packager<Snack>` |

/*
// interface Packager<in T> {
// package: (item: T) => void
// }

//* Invariance
/*
// interface ProducerPackager<T> {
// produce: () => T
// package: (item: T) => void
// }
/*
// let cookieProducerPackager: ProducerPackager<Cookie> = {
// produce() {
// return new Cookie('dark')
// },
// package(arg: Cookie) {},
// }

// let snackProducerPackager: ProducerPackager<Snack> = {
// produce() {
// return Math.random() > 0.5
// ? new Cookie('milk')
// : new Pretzel(true)
// },
// package(item: Snack) {
// if (item instanceof Cookie) {
// /* Package cookie */
// } else if (item instanceof Pretzel) {
// /* Package pretzel */
// } else {
// /* Package other snacks? */
// }
// },
// }

/*
// //? Type equivalence check
// cookieProducerPackager = snackProducerPackager
// snackProducerPackager = cookieProducerPackager

/*
// | Cookie | direction | Snack |
// |---------------------------|---------------|-----------------------|
// | `Cookie` | --- is a ---> | `Snack` |
// | `ProducerPackager<Cookie>`| x x x x x x | `ProducerPackager<Snack>` |

//* Bivariance

/*
// function cookieQualityCheck(cookie: Cookie): boolean {
// return Math.random() > 0.1
// }

// function snackQualityCheck(snack: Snack): boolean {
// if (snack instanceof Cookie) return cookieQualityCheck(snack)
// else return Math.random() > 0.16 // pretzel case
// }

/*
// // A function type for preparing a bunch of food items
// // for shipment. The function must be passed a callback
// // that will be used to check the quality of each item.
// type PrepareFoodPackage<T> = (
// uncheckedItems: T[],
// qualityCheck: (arg: T) => boolean,
// ) => T[]

/*
// // Prepare a bunch of snacks for shipment
// let prepareSnacks: PrepareFoodPackage<Snack> = (
// uncheckedItems,
// callback,
// ) => uncheckedItems.filter(callback)

// // Prepare a bunch of cookies for shipment
// let prepareCookies: PrepareFoodPackage<Cookie> = (
// uncheckedItems,
// callback,
// ) => uncheckedItems.filter(callback)

/*
// const cookies = [
// new Cookie('dark'),
// new Cookie('milk'),
// new Cookie('white'),
// ]
// const snacks = [
// new Pretzel(true),
// new Cookie('milk'),
// new Cookie('white'),
// ]
// prepareSnacks(cookies, cookieQualityCheck)
// prepareSnacks(snacks, cookieQualityCheck)
// prepareCookies(cookies, snackQualityCheck)

/*
//? What if we turn `strictFunctionTypes` on and off?

//* What do variance helpers do for you?
/*
// interface Example<in T> {
// package: (item: T) => void
// // produce: () => T;
// }

/**/
export default {}
1 change: 1 addition & 0 deletions packages/notes-intermediate-ts-v2/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"noUnusedLocals": false,
"noImplicitAny": true,
"noImplicitThis": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"checkJs": true,
"esModuleInterop": false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Intro
date: "2021-06-10T09:00:00.000Z"
date: "2023-10-25T09:00:00.000Z"
description: |
We'll discuss the goals and agenda of this course, and how to get up and
running with the workshop project in 2 minutes or less.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Declaration Merging
date: "2021-06-10T09:00:00.000Z"
date: "2023-10-25T09:00:00.000Z"
description: |
In order to truly understand how types and values "stack" on
each other, we'll first tackle the concept of declaration merging.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Modules & CJS interop
date: "2021-06-10T09:00:00.000Z"
date: "2023-10-25T09:00:00.000Z"
description: |
Although most of the code we write today is in the form of
ES modules, plenty of dependencies are packaged in the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Generics Scopes and Constraints
date: "2021-06-10T09:00:00.000Z"
date: "2023-10-25T09:00:00.000Z"
description: |
In this chapter, we'll learn about scopes and constraints, as they pertain to
type params, and what the language would look like if we didn't have these
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Conditional Types
date: "2021-06-10T09:00:00.000Z"
date: "2023-10-25T09:00:00.000Z"
description: |
Conditional types can be thought of as "a ternary operator, for types".
While there is no "control flow" in a world where we're describing constraints with types
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Inference with conditional types
date: "2021-06-10T09:00:00.000Z"
date: "2023-10-25T09:00:00.000Z"
description: |
Conditional types are not just for switching behavior based
on comparison -- they can be used with an 'infer' keyword
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Mapped Types
date: "2021-06-10T09:00:00.000Z"
date: "2023-10-25T09:00:00.000Z"
description: |
Mapped types are a powerful feature in TypeScript that allows you to create new types based on existing ones by transforming properties in a controlled manner.

Expand Down
Loading
Loading