[TypeScript] 03 Skills

`any` is convenient, as it basically disables all type-checks[1]

fetch

async function loadProducts(): Promise<Product[]> {
const response = await fetch('https://api.mysite.com/products')
const products: unknown = await response.json()
return products as Product[]
}

type assertion

const a = expr as any as T; // use two assertions,针对 ts 断言报错,实际上合法的
// or
const a = <T> expr;

// Non-null Assertion Operator (Postfix !)
function liveDangerously(x?: number | null) {
// No error
console.log(x!.toFixed());
}

type predicates

function isArrayOfProducts (obj: unknown): obj is Product[] {
return Array.isArray(obj) && obj.every(isProduct)
}

function isProduct (obj: unknown): obj is Product {
return obj != null
&& typeof (obj as Product).id === 'string'
}

async function loadProducts(): Promise<Product[]> {
const response = await fetch('https://api.mysite.com/products')
const products: unknown = await response.json()
if (!isArrayOfProducts(products)) {
throw new TypeError('Received malformed products API response')
}
return products
}

narrowing for union

// never for exhaustiveness checking
type Shape = Circle | Square;
&nbsp;
function getArea(shape: Shape) {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.sideLength ** 2;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}

readonly

interface ReadonlyStringArray {
readonly [index: number]: string;
}
&nbsp;
let myArray: ReadonlyStringArray = getReadOnlyStringArray();
myArray[2] = "Mallory";
Index signature in type 'ReadonlyStringArray' only permits reading.

infer

    1. 条件类型为我们提供了一种使用 infer 关键字从 true 分支中与之进行比较的类型中进行推断的方法
    2. 使用 infer 关键字编写一些有用的助手类型别名
// <1>
type Flatten<Type> = Type extends Array<infer Item>
? Item
: Type;

// <2>
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
? Return
: never;
&nbsp;
type Num = GetReturnType<() => number>; // type Num = number
&nbsp;
type Str = GetReturnType<(x: string) => string>; // type Str = string
&nbsp;
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>; // type Bools = boolean[]

// <3> returns a similar function type, but without the first argument.
type OmitFirstArg<F> = F extends (first: any, ...rest: infer A) => infer R
? (...args: A) => R
: never;

createInstance

/*class BeeKeeper {
hasMask: boolean;
}

class ZooKeeper {
nametag: string;
}

class Animal {
numLegs: number;
}

class Bee extends Animal {
keeper: BeeKeeper;
}

class Lion extends Animal {
keeper: ZooKeeper;
}*/

function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}

//createInstance(Lion).keeper.nametag;
//createInstance(Bee).keeper.hasMask;

type 三目运算

// SomeType extends OtherType ? TrueType : FalseType;
type NameOrId<T extends number | string> = T extends number
? IdLabel
: NameLabel;

function createLabel<T extends number | string>(idOrName: T): NameOrId<T> {
throw "unimplemented";
}

let a = createLabel("typescript"); // ^ = let a: NameLabel

let b = createLabel(2.8); // ^ = let b: IdLabel

let c = createLabel(Math.random() ? "hello" : 42); // ^ = let c: NameLabel | IdLabel

Date:
Words:
630
Time to read:
3 mins