[Typescript] Making TypeScript Stick - 3
1.
const values = [3, "14", [21]]
for (let a in values) {
// ^?
}
for (let b of values) {
// ^?
}
.
.
.
.
Answer:
for...in loop: The for...in
statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
for..of loop: The for...of
statement creates a loop iterating over iterable objects, including: built-in String
, Array
, array-like objects (e.g., arguments
or NodeList
), TypedArray
, Map
, Set
, and user-defined iterables. It invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
For ..in: use string key, so that `a` is string type
For ..of: `b` will be each value, so will be `number | string | number[]`
2.
class Person {
constructor(public name: string) {}
}
class Library {
librarians: Person[] = []
}
const localLibrary = Library
// ^?
const otherLibrary = new Library()
// ^?
.
.
.
.
Answer:
const localLibrary: typeof Library
const otherLibrary: Library
3.
class AsyncManager {
constructor(arg: 0 | 4 | string) {
if (arg > 0 || arg <= 0) {
new Promise((resolve, reject) => {
arg
//^?
})
}
}
}
.
.
.
.
Answer:
(parameter) arg: string | 0 | 4
// "4" > 0 --> true
If doing this, will restrict `arg` type:
if (typeof arg === "number" && (arg > 0 || arg <= 0)) {
new Promise((resolve, reject) => {
arg
//^?
})
}
arg: string | 0 | 4
4.
enum CoinResult {
heads,
tails,
}
function flipCoin(): CoinResult {
return Math.random() > 0.5
? CoinResult.heads
: CoinResult.tails
}
function main() {
const flipResult = flipCoin()
if (flipResult === CoinResult.heads) {
console.log("heads")
} else if (flipResult === CoinResult.tails) {
console.log("tails")
} else {
flipResult
// ^?
}
}
.
.
.
.
Answer:
const flipResult: never
5.
function getValue(): [number] | Promise<number> {
if (Math.random() > 0.5) return [42]
else return Promise.resolve(42)
}
async function main() {
const resolved = await getValue()
// ^?
}
.
.
.
.
Answer:
const resolved: number | [number]
6.
let x: number | any = 41
const y = x
// ^?
.
.
.
.
Answer:
let x = 41 // x: number
const x = 41 // x: 41
// but say that x is a number type
const x: number = 41 // x: number
// if say taht x can be any type as well
const x: number | any = 41 // x: any
// Union type, if you union any type with `any`, the type will be `any`
const y = x // y: any
---
let x = 41
const y = x; //y: number, y will infer as number
---
const x = 41
const y = x; // y: 41
7.
const values = [4, 1, null, 21, 45, 32]
const filtered = values.filter((val) => val !== null)
// ^?
.
.
.
.
Answer:
const filtered: (number | null)[]
If you just want number[], you need to use type guard function:
function isNumber<T>(x: T | undefined | null): x is T {
return typeof x === "number"
}
const filtered = values.filter(isNumber) // number[]
8.
class Person {
static species = "Homo Sapien"
constructor(public name: string) {}
}
const p = new Person("mike")
let x: keyof typeof Person
// ^?
let y: keyof typeof p
// ^?
.
.
.
.
.
Answer:
let x: "prototype" | "species"
let y: "name"
static prop cannot be access by instance, therefore y doesn't contains "species".
9.
enum Language {
JavaScript,
TypeScript = "TS",
}
let lang1: Language = Language.JavaScript
// ^?
let lang2: Language = Language.TypeScript
// ^?
Math.round(lang1)
Math.round(lang2)
.
.
.
.
Answer:
// ERROR
Math.round(lang2) // Argument of type 'Language' is not assignable to parameter of type 'number'.
10.
async function tryFetch(url: RequestInfo) {
try {
const val = await (await fetch(url)).json()
return val
} catch (err) {
console.error(err)
return undefined
}
}
async function main() {
const val = await tryFetch("https://example.com")
// ^?
}
.
.
.
.
Answer:
const val: any
If change:
const val = await (await fetch(url)).json() as string
Then:
const val: string | undefined
If change:
async function tryFetch(url: RequestInfo) {
try {
const val = await (await fetch(url)).json()
throw new Error("err")
} catch (err) {
console.error(err)
return undefined
}
}
Then:
const val: undefined
which comes from catch block `return undefined`.
If change:
async function tryFetch(url: RequestInfo) {
try {
const val = await (await fetch(url)).json()
throw new Error("err")
} catch (err) {
console.error(err)
if (err instanceof Error) {
throw err
} else {
throw new Error("err")
}
}
}
Then:
const val: void
because we don't do return from catch block, therefore val never get assignmenet.
We need to do try-catch block again.
11.
class Book {
title: string = ""
author: string = ""
}
const keys = Object.keys(new Book())
// ^?
.
.
.
.
Answer:
const keys: string[]