以下是我的自定义类型:
type KeyMap<T> = { [K in keyof T]: keyof Pick<T, K> }
接着是一个用于自定义类型的简单界面:
interface MyInterface {
a: string;
b: string;
}
当我的类型的变量在类之外定义时,TypeScript很高兴:
const member: KeyMap<MyInterface> = {
a: 'a',
b: 'b'
}
但是,当我使用类型为KeyMap
的抽象成员定义一个抽象类并尝试实现它时,它将无法正常工作。例如:
abstract class BaseClass<T> {
protected abstract member: KeyMap<T>
protected abstract method: () => void;
}
class DerivedClass extends BaseClass<MyInterface> {
// TypeScript reports that property 'a' is not compatible with '"a"'
protected member = {
a: 'a',
b: 'b'
};
protected method = () => console.log('');
}
直接在抽象或派生类中定义成员似乎可行。例如:
abstract class BaseClass {
public member: KeyMap<MyInterface> = {
a: 'a',
b: 'b'
}
protected abstract method: () => void;
}
class DerivedClass extends BaseClass {
public derivedMember: KeyMap<MyInterface> = {
a: 'a',
b: 'b'
}
protected method = () => console.log('');
}
将成员更改为其他类型也是如此:
abstract class BaseClass<T> {
protected abstract member: { c: string, d: string };
protected abstract method: () => void;
}
class DerivedClass extends BaseClass<MyInterface> {
protected member = {
c: 'c',
d: 'd'
};
protected method = () => console.log('');
}
为什么TypeScript在派生类中member
的实现在类之外工作并且未标记为抽象时将其报告为错误?
答案 0 :(得分:1)
类成员是类型,而与基类中的内容无关,只有这样,派生类才会被检查与基类的兼容性。由于成员是根据初始化值键入的,因此typescript不会将文字类型用于属性类型(只有某些地方TS不会扩展文字类型,这也不是其中之一)
您可以做的最好的想法就是为成员使用一个明确的类型注释,就像您已经说过的在问题中尝试过的那样:
class DerivedClass extends BaseClass<MyInterface> {
protected member: KeyMap<MyInterface> = {
a: 'a',
b: 'b'
};
protected method = () => console.log('');
}