【问题标题】:Error when trying to assigning interface尝试分配接口时出错
【发布时间】:2018-08-14 23:51:08
【问题描述】:

我有以下类/接口:

class Klass {
  baseAttr: string;
}

class ChildKlass extends Klass {
  childAttr: string;
}

interface T1<T extends Klass = Klass> {
  readonly display: ReadonlyArray<keyof T>;
}

class T1Klass implements T1<ChildKlass> {
  readonly display: ReadonlyArray<keyof ChildKlass> = ['childAttr'];
}

上面一切正常...


当我尝试创建一个值应该是的“字典”时,问题就来了:

t1 - “实现 T1 的类的实例”;
klass - “扩展 Klass 的类的实例”

interface ConstructableT1 {
  new(): T1;
}

interface T1KlassDictionary {
  [key: string]: {
    // Since I can't just say t1 is typeof T1, I created the ConstructableT1 interface
    t1?: ConstructableT1,
    klass?: typeof Klass
  };
}

当我尝试实例化 object:

const dictionary: T1KlassDictionary = {
  test: {
    t1: T1Klass,
    klass: ChildKlass
  }
};

...它给了我以下错误:

类型“typeof T1Klass”不可分配给类型“ConstructableT1”。

Playground link

我做错了什么?

【问题讨论】:

    标签: typescript typescript2.0


    【解决方案1】:

    类型“typeof T1Klass”不可分配给类型“ConstructableT1”。

    TypeScript 编译器有时会缩短错误消息。在这种情况下,它没有说明为什么 typeof T1Klass 不能分配给 ConstructableT1

    要了解原因,让我们尝试将一个分配给另一个:

    let a: typeof T1Klass;
    let b: ConstructableT1 = a;
    

    现在我们得到

    Type 'typeof T1Klass' is not assignable to type 'ConstructableT1'.
      Type 'T1Klass' is not assignable to type 'T1<Klass>'.
        Types of property 'display' are incompatible.
          Type 'ReadonlyArray<"id" | "attr">' is not assignable to type 'ReadonlyArray<"attr">'.
            Type '"id" | "attr"' is not assignable to type '"attr"'.
              Type '"id"' is not assignable to type '"attr"'.
    

    这似乎是合理的 - 一个可能的键值 - “id” - 不能分配给文字类型“attr”的值。

    一种可能的解决方案是使interface ConstructableT1 泛型,因此编译器将知道t1 的实际类型,并且不会对不兼容的泛型参数(T1Klass)使用默认值:

    interface T1<T extends Klass = Klass> {
        readonly display: ReadonlyArray<keyof T>;
    }
    
    interface ConstructableT1<T extends Klass = Klass> {
        new(): T1<T>;
    }
    
    
    
    class T1Klass implements T1<ChildKlass> {
        readonly display: ReadonlyArray<keyof ChildKlass> = ['id'];
    }
    
    
    class Klass {
        attr: string;
    }
    
    class ChildKlass extends Klass {
        id: string;
    }
    
    interface T1KlassDictionary {
        [key: string]: {
            t1?: ConstructableT1<ChildKlass>,
            klass?: typeof Klass
        };
    }
    
    const dictionary: T1KlassDictionary = {
        test: {
            t1: T1Klass,
            klass: ChildKlass
        }
    };
    

    更新问题得到澄清:

    当我尝试创建一个值的“字典”时,问题就来了 应该是:

    t1 - “实现 T1 的类的实例”;类 - “一个实例 扩展类的类"

    那么我会说你有错误的类型 t1klass。您将它们声明为构造函数 - 也就是说,dictionary.t1 可用于创建这样的实例

    const inst = new dictionary.test.t1();
    

    操场说这种方式创建的inst的类型是const inst: T1&lt;ChildKlass&gt;

    如果字典应该包含实例,则应该这样声明

    interface T1KlassDictionary {
        [key: string]: {
            t1?: T1<ChildKlass>,
            klass?: Klass
        };
    }
    

    并使用new()创建的实例进行初始化

    const dictionary: T1KlassDictionary = {
        test: {
            t1: new T1Klass(),
            klass: new ChildKlass()
        }
    };
    

    然后您可以访问实例属性:

    const attr = dictionary.test.klass.attr; 
    // but no id because declared type of `klass`
    //  is `Klass` which does not have `id`
    
    const attr = dictionary.test.t1.display;
    

    【讨论】:

    • 感谢您的回答和解释...但是我希望能够访问这些类的属性,例如:dictionary.test.t1.displaydictionary.test.klass.id,我不知道该怎么做。事实上,我忘了在 OP 中提到这一点(现在添加)。你能帮我吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    • 2012-03-26
    • 1970-01-01
    相关资源
    最近更新 更多