美文网首页
Typescript 中的协变和逆变

Typescript 中的协变和逆变

作者: 一大碗豆浆 | 来源:发表于2018-10-28 11:12 被阅读18次

    Typescript的协变和逆变和C# Scala中的类似,但是Typescript的会自动算出来接口属于协变还是逆变,C# Scala中需要显示声明in out标记接口。 在typescript需要在tsconfig中使用strictFunctionTypes参数开启逆变检查,否则就是双变(协变或者逆变)。


    逆变接口

    接口中泛型只作为函数类型参数
    interface Animal {
        Eat(): void
    }
    
    interface Dog extends Animal{
        Bark():void
    }
    
    interface Cat extends Animal{
        Meow():void
    }
    
    interface Comparer<T> {
        compareA: (a: T, b: T) => number;
    }
    
    逆变接口的赋值类型检查
    declare let animalComparer: Comparer<Animal>;
    declare let dogComparer: Comparer<Dog>;
    
    animalComparer = dogComparer; 
    /*
        错误, 因为调用 animalComparer(Dog)的时候,
        dogComparer会接受到一个Animal类型的参数,这是有风险的
    */
    dogComparer = animalComparer;  // 正确
    
    例外情况
    interface Comparer<T> {
        compareA(a: T, b: T): number;
    }
    declare let animalComparer: Comparer<Animal>;
    declare let dogComparer: Comparer<Dog>;
    
    animalComparer = dogComparer; //正确
    dogComparer = animalComparer;  // 正确
    /*
        因为
            compareA(a: T, b: T): number;
        和
            compareA: (a: T, b: T) => number;
        不太一样,前者认为是双变, 后者认为是逆变。这样做的相当于把方法类型的声明排除在外,目的在于为了确保带泛型的类和接口(如 Array)总体上仍然保持协变。
    */
    

    协变接口

    接口中泛型只作为函数类型返回值
    interface Animal {
        Eat(): void
    }
    
    interface Dog extends Animal{
        Bark():void
    }
    
    interface Cat extends Animal{
        Meow():void
    }
    
    interface Comparer<T> {
        compareB: () => T;
    }
    
    协变接口的赋值类型检查
    declare let animalComparer: Comparer<Animal>;
    declare let dogComparer: Comparer<Dog>;
    
    animalComparer = dogComparer; 
    // 正确
    dogComparer = animalComparer;  
    /*
        错误, 因为调用 dogComparer(Dog)的时候,
        animalComparer会返回一个Animal类型的值,这是有风险的
    */
    

    总结

    协变和抗逆变的意义在于泛型类型的类型转换带来的类型安全问题。
    协变类型的接口只能允许派生类泛型赋值给父类泛型I<Dog> -> I<Animal>
    逆变类型的接口只能允许父类泛型赋值给派生类泛型 I<Animal> -> I<Dog>

    相关文章

      网友评论

          本文标题:Typescript 中的协变和逆变

          本文链接:https://www.haomeiwen.com/subject/nrlrtqtx.html