TypeScript 学习笔记--高级类型(二)

57 阅读2分钟

一、字符串字面量类型

指定固定值的字符串

字符串字面量类型可以与联合类型,类型保护和类型别名很好的配合

示例

type Easing = "ease-in" | "ease-out" | "ease-in-out";
class UIElement {
    animate(dx: number, dy: number, easing: Easing) {
        if (easing === "ease-in") {
            // ...
        }
        else if (easing === "ease-out") {
        }
        else if (easing === "ease-in-out") {
        }
        else {
            // error! should not pass null or undefined.
        }
    }
}

let button = new UIElement();
button.animate(0, 0, "ease-in");
// 只能从三种允许的字符中选择其一来做为参数传递,传入其它值则会产生错误
button.animate(0, 0, "uneasy"); // error: "uneasy" is not allowed here

用于区分函数重载

function createElement(tagName: "img"): HTMLImageElement;
function createElement(tagName: "input"): HTMLInputElement;
// ... more overloads ...
function createElement(tagName: string): Element {
    // ... code goes here ...
}

二、数字字面量类型

function rollDie(): 1 | 2 | 3 | 4 | 5 | 6 {
    // ...
}

三、索引类型

索引类型查询操作符: keyof T   任何类型 T, keyof T的结果为 T上已知的公共属性名的联合

示例

interface Person {
    name: string;
    age: number;
}
let personProps: keyof Person; // 'name' | 'age'

T[K], 索引访问操作符, 示例如下:

// getProperty里的 o: T和 name: K,意味着 o[name]: T[K]。 当你返回 T[K]的结果,编译器会实例化键的真实类型,因此 getProperty的返回值类型会随着你需要的属性改变。

function getProperty<T, K extends keyof T>(o: T, name: K): T[K] {
    return o[name]; // o[name] is of type T[K]
}

索引类型和字符串索引签名联合使用

keyof和 T[K]与字符串索引签名进行交互

如果你有一个带有字符串索引签名的类型,那么 keyof T会是 string。 并且 T[string]为索引签名的类型

interface Map<T> {
    [key: string]: T;
}
let keys: keyof Map<number>; // string
let value: Map<number>['foo']; // number

四、映射类型

从旧类型中以某种形式创建新类型

类型拆包:

这个拆包推断只适用于同态的映射类型。 如果映射类型不是同态的,那么需要给拆包函数一个明确的类型参数。

Readonly, Partial和 Pick是同态的,但 Record不是。 因为 Record并不需要输入类型来拷贝属性,所以它不属于同态

示例

function unproxify<T>(t: Proxify<T>): T {
    let result = {} as T;
    for (const k in t) {
        result[k] = t[k].get();
    }
    return result;
}

let originalProps = unproxify(proxyProps)