-
Notifications
You must be signed in to change notification settings - Fork 531
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Intermediate TypeScript v2 notes (#913)
* notes: nullish values * notes: modules and cjs interop * notes: fixes to modules and cjs interop * WIP * notes: generic scopes and constraints * notes: generic scopes and constraints - updated * WIP * WIP * notes: conditional types * notes: infer * notes: mapped types * WIP * fix lint error
- Loading branch information
1 parent
fa23cc2
commit 3b6cd18
Showing
29 changed files
with
1,178 additions
and
118 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
117 changes: 117 additions & 0 deletions
117
packages/notes-intermediate-ts-v2/src/04-nullish-values.ts
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,117 @@ | ||
//* Null | ||
|
||
const userInfo = { | ||
name: 'Mike', | ||
email: '[email protected]', | ||
secondaryEmail: null, // user has no secondary email | ||
} | ||
|
||
//* Undefined | ||
/* | ||
// interface FormInProgress { | ||
// createdAt: Date | ||
// data: FormData | ||
// completedAt?: Date | ||
// } | ||
// const formInProgress: FormInProgress = { | ||
// createdAt: new Date(), | ||
// data: new FormData(), | ||
// } | ||
// function submitForm() { | ||
// const myDate: Date = formInProgress.completedAt | ||
// formInProgress.completedAt = new Date() | ||
// } | ||
//* void | ||
/* | ||
// console.log(`console.log returns nothing.`) | ||
//* Non-null assertion operator | ||
/* | ||
// type GroceryCart = { | ||
// fruits?: { name: string; qty: number }[] | ||
// vegetables?: { name: string; qty: number }[] | ||
// } | ||
// const cart: GroceryCart = {} | ||
// cart.fruits.push({ name: 'kumkuat', qty: 1 }) | ||
// cart.fruits!.push({ name: 'kumkuat', qty: 1 }) | ||
//* Definite assignment assertion | ||
/* | ||
// class ThingWithAsyncSetup { | ||
// setupPromise: Promise<any> | ||
// isSetup: boolean | ||
// constructor() { | ||
// this.setupPromise = new Promise((resolve) => { | ||
// this.isSetup = false | ||
// return this.doSetup(resolve) | ||
// }).then(() => { | ||
// this.isSetup = true | ||
// }) | ||
// } | ||
// private async doSetup(resolve: (value: unknown) => void) { | ||
// // some async stuff | ||
// } | ||
// } | ||
//* Optional Chaining | ||
/* | ||
// type Payment = { | ||
// id: string | ||
// amount: number | ||
// createdAt: Date | ||
// } | ||
// type Invoice = { | ||
// id: string | ||
// due: number | ||
// payments: Payment[] | ||
// lastPayment?: Payment | ||
// createdAt: Date | ||
// } | ||
// type Customer = { | ||
// id: string | ||
// lastInvoice?: Invoice | ||
// invoices: Invoice[] | ||
// } | ||
// type ResponseData = { | ||
// customers?: Customer[] | ||
// customer?: Customer | ||
// } | ||
// function getLastPayment(data: ResponseData): number | undefined { | ||
// const { customer } = data | ||
// if (!customer) return | ||
// const { lastInvoice } = customer | ||
// if (!lastInvoice) return | ||
// const { lastPayment } = lastInvoice | ||
// if (!lastPayment) return | ||
// return lastPayment.amount | ||
// } | ||
/* | ||
// function getLastPayment2(data: ResponseData): number | undefined { | ||
// return data?.customer?.lastInvoice?.lastPayment?.amount | ||
// } | ||
//* Nullish Coalescing | ||
/* | ||
// function setVolume(v: number): void {} | ||
// type PlayerConfig = { | ||
// volume?: 0 | 25 | 50 | 75 | 100 | ||
// } | ||
// function initializePlayer(config: PlayerConfig): void { | ||
// const vol = | ||
// typeof config.volume === 'undefined' ? 50 : config.volume | ||
// setVolume(vol) | ||
// } | ||
/**/ | ||
export default {} |
5 changes: 5 additions & 0 deletions
5
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/banana.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,5 @@ | ||
class Banana { | ||
peel() {} | ||
} | ||
|
||
module.exports = { Banana } |
3 changes: 3 additions & 0 deletions
3
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/berries/berry-base.ts
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 @@ | ||
export abstract class BerryBase { | ||
abstract color: string | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/berries/blueberry.ts
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,5 @@ | ||
import { BerryBase } from "./berry-base"; | ||
|
||
export class Blueberry extends BerryBase{ | ||
readonly color: 'blue'; | ||
} |
3 changes: 3 additions & 0 deletions
3
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/berries/index.ts
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 @@ | ||
export * from './blueberry'; | ||
export * from './strawberry'; | ||
export * from './raspberry'; |
17 changes: 17 additions & 0 deletions
17
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/berries/raspberry.ts
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,17 @@ | ||
import { BerryBase } from './berry-base' | ||
|
||
export class Raspberry extends BerryBase { | ||
constructor(public readonly color: 'red' | 'black') { | ||
super() | ||
} | ||
} | ||
|
||
export function pickRaspberries(time: number): Raspberry[] { | ||
const berries: Raspberry[] = [] | ||
console.log('picking raspberries') | ||
const numPicked = Math.round(Math.random() * 15) | ||
while (berries.length < numPicked) { | ||
berries.push(new Raspberry(Math.random() > 0.5 ? 'red' : 'black')) | ||
} | ||
return berries | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/berries/strawberry.ts
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,5 @@ | ||
import { BerryBase } from "./berry-base"; | ||
|
||
export class Strawberry extends BerryBase{ | ||
readonly color: 'red'; | ||
} |
2 changes: 2 additions & 0 deletions
2
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/citrus.ts
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,2 @@ | ||
export function lemon () {} | ||
export function lime () {} |
1 change: 1 addition & 0 deletions
1
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/global.d.ts
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 @@ | ||
// Global types |
68 changes: 68 additions & 0 deletions
68
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/index.ts
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 @@ | ||
//* ES module imports and exports | ||
|
||
/* | ||
// //? named imports | ||
// import { Blueberry, Raspberry } from './berries' | ||
// import Kiwi from './kiwi' // default import | ||
// export function makeFruitSalad() {} // named export | ||
// export default class FruitBasket {} // default export | ||
// export { lemon, lime } from './citrus' // re-export | ||
// export * as berries from './berries' // re-export entire module as a single namespace | ||
/* | ||
// //? namespace import | ||
// import * as allBerries from './berries' // namespace import | ||
// allBerries.Strawberry // using the namespace | ||
// allBerries.Blueberry | ||
// allBerries.Raspberry | ||
// export * from './berries' // namespace re-export | ||
//* Importing types | ||
/* | ||
// let x: Raspberry = { color: 'red' } | ||
// const y = new Raspberry('red') | ||
//* Type-only imports | ||
/* | ||
// import type { Strawberry } from './berries/strawberry' | ||
// let z: Strawberry = { color: 'red' } | ||
// new Strawberry() | ||
//* CommonJS Interop | ||
/* | ||
// //? "import as a namespace" | ||
// import * as bananaNamespace from './banana' | ||
// const banana = new bananaNamespace.Banana() | ||
/* | ||
//? import as a single thing (rare) | ||
// import * as melonNamespace from './melon' | ||
//? special ts import | ||
// import Melon = require('./melon') | ||
// const melon = new Melon() | ||
// melon.cutIntoSlices() | ||
//* Native ES Module support | ||
/* | ||
// import * as bananaNamespace from './banana.cjs' | ||
// package.json --> 'type: module', 'type: commonjs' | ||
//* Importing non-ts things | ||
/* | ||
// import img from "./ts-logo.png" | ||
//? Add to global.d.ts | ||
// declare module '*.png' { | ||
// const imgUrl: string | ||
// export default imgUrl | ||
// } | ||
/**/ | ||
export default {} |
3 changes: 3 additions & 0 deletions
3
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/kiwi.ts
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 @@ | ||
export default class Kiwi { | ||
color = 'green'; | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/melon.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,5 @@ | ||
class Melon { | ||
cutIntoSlices() { } | ||
} | ||
|
||
module.exports = Melon |
Binary file added
BIN
+3.2 KB
packages/notes-intermediate-ts-v2/src/05-modules-and-cjs-interop/ts-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions
127
packages/notes-intermediate-ts-v2/src/06-generic-scopes-and-constraints.ts
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,127 @@ | ||
//* Generic Constraints - A motivating use case | ||
const phoneList = [ | ||
{ customerId: '0001', areaCode: '321', num: '123-4566' }, | ||
{ customerId: '0002', areaCode: '174', num: '142-3626' }, | ||
{ customerId: '0003', areaCode: '192', num: '012-7190' }, | ||
{ customerId: '0005', areaCode: '402', num: '652-5782' }, | ||
{ customerId: '0004', areaCode: '301', num: '184-8501' }, | ||
] | ||
const phoneDict = { | ||
'0001': { | ||
customerId: '0001', | ||
areaCode: '321', | ||
num: '123-4566', | ||
}, | ||
'0002': { | ||
customerId: '0002', | ||
areaCode: '174', | ||
num: '142-3626', | ||
}, | ||
/*... and so on */ | ||
} | ||
|
||
function listToDict<T>( | ||
list: T[], // array as input | ||
idGen: (arg: T) => string, // fn for obtaining item's id | ||
): { [k: string]: T } { | ||
// create dict to fill | ||
const dict: { [k: string]: T } = {} | ||
|
||
for (let item of list) { | ||
// for each item | ||
dict[idGen(item)] = item // make a key store in dict | ||
} | ||
|
||
return dict // result | ||
} | ||
/* | ||
// interface HasId { | ||
// id: string | ||
// } | ||
// interface Dict<T> { | ||
// [k: string]: T | ||
// } | ||
// function listToDict(list: HasId[]): Dict<HasId> { | ||
// const dict: Dict<HasId> = {} | ||
// list.forEach((item) => { | ||
// dict[item.id] = item | ||
// }) | ||
// return dict | ||
// } | ||
/* | ||
//? Let's make it | ||
// function listToDict<T>(list: T[]): Dict<T> { | ||
//* Describing the constraint | ||
/* | ||
// function listToDict<T extends HasId>(list: T[]): Dict<T> { | ||
//* Scopes and Type Parameters | ||
/* | ||
// function eatApple(bowl: any, eater: (arg: any) => void) {} | ||
// function receiveFruitBasket(bowl: any) { | ||
// console.log('Thanks for the fruit basket!') | ||
// // only `bowl` can be accessed here | ||
// eatApple(bowl, (apple: any) => { | ||
// // both `bowl` and `apple` can be accessed here | ||
// }) | ||
// } | ||
// // outer function | ||
// function tupleCreator<T>(first: T) { | ||
// // inner function | ||
// return function finish<S>(last: S): [T, S] { | ||
// return [first, last] | ||
// } | ||
// } | ||
// const finishTuple = tupleCreator(3 as const) | ||
// const t1 = finishTuple(null) | ||
// const t2 = finishTuple([4, 8, 15, 16, 23, 42]) | ||
//* Best practices | ||
// interface HasId { | ||
// id: string | ||
// } | ||
// interface Dict<T> { | ||
// [k: string]: T | ||
// } | ||
// function example1<T extends HasId[]>(list: T) { | ||
// return list.pop() | ||
// // ^? | ||
// } | ||
// function example2<T extends HasId>(list: T[]) { | ||
// return list.pop() | ||
// // ^? | ||
// } | ||
// class Payment implements HasId { | ||
// static #next_id_counter = 1; | ||
// id = `pmnt_${Payment.#next_id_counter++}` | ||
// } | ||
// class Invoice implements HasId { | ||
// static #next_id_counter = 1; | ||
// id = `invc_${Invoice.#next_id_counter++}` | ||
// } | ||
// const result1 = example1([ | ||
// // ^? | ||
// new Payment(), | ||
// new Invoice(), | ||
// new Payment() | ||
// ]) | ||
// const result2 = example2([ | ||
// // ^? | ||
// new Payment(), | ||
// new Invoice(), | ||
// new Payment() | ||
// ]) | ||
/**/ | ||
export default {} |
Oops, something went wrong.