尝试分配接口时出错
Error when trying to assigning interface
我有以下 classes/interfaces:
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'];
}
以上一切正常...
当我尝试创建一个 "dictionary" 值应该是:
时出现问题
t1
- "an instance of class that implements T1";
klass
- "an instance of class that extends 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
}
};
...它给了我以下错误:
Type 'typeof T1Klass' is not assignable to type 'ConstructableT1'.
我做错了什么?
Type 'typeof T1Klass' is not assignable to type '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
}
};
更新 问题已澄清:
The problem comes when I try to create a "dictionary" where the value
should be:
t1 - "an instance of class that implements T1"; klass - "an instance
of class that extends Klass"
那我会说你 t1
和 klass
的类型有误。您将它们声明为构造函数 - 也就是说,dictionary.t1
可用于创建这样的实例
const inst = new dictionary.test.t1();
playground 说这样创建的 inst
的类型是 const inst: T1<ChildKlass>
.
如果字典应该包含实例,应该这样声明
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;
我有以下 classes/interfaces:
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'];
}
以上一切正常...
当我尝试创建一个 "dictionary" 值应该是:
时出现问题t1
- "an instance of class that implements T1";
klass
- "an instance of class that extends 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
}
};
...它给了我以下错误:
Type 'typeof T1Klass' is not assignable to type 'ConstructableT1'.
我做错了什么?
Type 'typeof T1Klass' is not assignable to type '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
}
};
更新 问题已澄清:
The problem comes when I try to create a "dictionary" where the value should be:
t1 - "an instance of class that implements T1"; klass - "an instance of class that extends Klass"
那我会说你 t1
和 klass
的类型有误。您将它们声明为构造函数 - 也就是说,dictionary.t1
可用于创建这样的实例
const inst = new dictionary.test.t1();
playground 说这样创建的 inst
的类型是 const inst: T1<ChildKlass>
.
如果字典应该包含实例,应该这样声明
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;