VueBloghyhero6

TS 高级类型

2024-09-24 / 2024-09-24 / 48次浏览
相对于高级类型,我更喜欢称之为高阶类型,为什么? 常规简单业务根本使用不到,首先第一个交叉类型,就是在复杂业务中混入才会使用到。

而且交叉类型文档也写的比较抽象

function extend<T, U>(first: T, second: U): T & U {
    let result = <T & U>{};
    for (let id in first) {
        (<any>result)[id] = (<any>first)[id];
    }
    for (let id in second) {
        if (!result.hasOwnProperty(id)) {
            (<any>result)[id] = (<any>second)[id];
        }
    }
    return result;
}

class Person {
    constructor(public name: string) { }
}
interface Loggable {
    log(): void;
}
class ConsoleLogger implements Loggable {
    log() {
        // ...
    }
}
var jim = extend(new Person("Jim"), new ConsoleLogger());
var n = jim.name;
jim.log();

像jim 就既有 name ,又能输出log 函数

比如下面GPT 给出的这个例子
有个用户系统,用户对象要同时具有下面功能:
身份信息(Person)
日志功能(Loggable)
序列化功能(Serializable)

可以通过交叉类型将这些功能组合到一起:

interface Serializable {
    serialize(): string;
}

class Person {
    constructor(public name: string) {}
}

class Logger implements Loggable {
    log() {
        console.log("Logging...");
    }
}

class Serializer implements Serializable {
    serialize() {
        return JSON.stringify(this);
    }
}

function extend<T, U>(first: T, second: U): T & U {
    let result = <T & U>{};
    for (let id in first) {
        (<any>result)[id] = (<any>first)[id];
    }
    for (let id in second) {
        if (!result.hasOwnProperty(id)) {
            (<any>result)[id] = (<any>second)[id];
        }
    }
    return result;
}

// 创建一个既是 Person,又有日志功能和序列化功能的对象
let user = extend(new Person("Alice"), extend(new Logger(), new Serializer()));

user.log(); // 来自 Logger
console.log(user.serialize()); // 来自 Serializer
console.log(user.name); // 来自 Person

联合类型
这个相对还好
let a: number | string = 111;
说明 a 既可以是数字也可以是字符串

用户自定义断言,有时候用户自己知道自己传的类型一定是什么,但是TS本身编译器不知道

所以会用到,
用户自定义类型保护的定义
用户自定义类型保护的关键在于返回值的类型谓词。类型谓词的语法是:
paramName is Type

interface Bird {
    fly();
    layEggs();
}


interface Fish {
    swim();
    layEggs();
}

function getSmallPet(): Fish | Bird {
    // ...
}

let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim();    // errors

比如例子给出的联合类型,只能有共通的方法可以使用, 所以要有用户自定义判断
function isFish(pet: Fish | Bird): pet is Fish {
    return (<Fish>pet).swim !== undefined;
}

// 'swim' 和 'fly' 调用都没有问题了

if (isFish(pet)) {
    pet.swim();
}
else {
    pet.fly();
}

typeof 保护类型 typeof a == 'string'  typeof a == 'number'

以及使用类型保护去除null

function f(sn: string | null): string {
    if (sn == null) {
        return "default";
    }
    else {
        return sn;
    }
}

也可以使用短路运算符:

function f(sn: string | null): string {
    return sn || 'default';
}


类型别名type 之前也看过