前端学习之旅 —— TypeScript 学习笔记(3)

44 阅读2分钟

进阶技巧

类型推断

  • 基础推断
let name = "pro";  // 推断为string

let age = 24;  // 推断为number

let x;  // 没有初始化的变量会被推断为any

  • 最佳通用类型推断

在推断时,考虑所有元素类型,找到兼容所有候选类型的最佳类型

let arr = [1, 2, 3, "pro"]; // 推断为 (string | number)[]
  • 上下文类型推断

通常包含函数的参数,赋值表达式的右边,类型断言,对象成员和数组字面量和返回值语句。

// 函数的返回值被推断为number
function add(a: number, b: number) {
    return a + b;
}

类型断言

  • 尖括号语法
let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length;
  • as语法
let someValue: any = "this is as string";

let strLength: number = (someValue as string).length;

类型缩小

类型缩小是通过一定的方式,缩小变量的类型范围,针对不同类型的变量,处理逻辑可能不同

例如,官方文档中给出的一个padLeft函数的例子,这个函数在输入字符串的左侧填充一定的padding,若padding为string,则直接拼接,若padding为number, 则填充padding数量的空格

function padLeft(padding: number | string, input: string): string {
    if (typeof padding === 'number') {
        return new Array(padding + 1).join(" ") + input;
        // return " ".repeat(padding) + input;
    }
    return padding + input;
}
  • typeof类型保护

如上面这段代码所示,通过typeof限定处理逻辑

  • 真值缩小

使用if&&||否定表达式等进行真值检查

function multiplyAll(
	values: number[] | undefined,
    factor: number
): number[] | undefined {
	if (!values) {
        return values;
    } else {
        return values.map(x => x * factor);
    }
}

这里过滤了使 if语句为假的所有类型,如0NaN空字符串nullundefined

  • 等值缩小

使用相等判断缩小检查类型,可以利用三等号同时判断类型的相同

function example(x: number | string, y: boolean | string) {
	if (x === y) {
		x.toUpperCase();
		y.toUpperCase();
	} else {
		console.log(x);
		console.log(y);
	}
}

这里因为x和y有只可能同为string,直接用三等号判断就可确定为string类型

  • in运算符缩小
type Fish = {
    swim: () => {}
}

type Bird = {
    fly: () => {}
}

function move(animal: Fish | Bird) {
    if ("fly" in animal) {
        return animal.fly;
    }
    return animal.swim;
}
  • instance运算符缩小
function logValue(x: Date | string) {
    if (x instanceof Date) {
        console.log(x.toLocaleString());
    } else {
        console.log(x.toUpperCase());
    }
}
  • 类型谓词

Type Predicate是TypeScript中的一种特殊语法,帮助TS编译器确定运行时的变量类型

type Fish = {
    swim: () => {}
}

type Bird = {
    fly: () => {}
}

function isFish(pet: Fish | Bird): pet is Fish {
    return (pet as Fish).swim !== undefined
}

通过这个isFish函数,可以确定对象是否为Fish类型,在具体代码逻辑中做到类型缩小

extends

  • 继承类
class Animal {
    name: string;
    constructor(_name: string) {
        this.name = _name;
    }
}

class Dog extends Animal {
    constructor(_name: string) {
        super(_name);
    }

    bark() {
        console.log(this.name + " is barking.");
    }
}
  • 泛型约束
function identity<T extends { length: number }>(arg: T): T {
    console.log(arg.length);
    return arg;
}

identity(3); // error
identity({ length: 1, name: 'pro' }); // ok
  • 条件类型
SomeType extends OtherType ? TrueType : FalseType;

interface Animal {
    live(): void
}

interface Dog extends Animal {
    bark(): void
}

type t1 = Dog extends Animal ? number : string; // t1 这里就是number类型了

let variable: t1 = 1;