下面是我的自定义类型:
type KeyMap<T> = { [K in keyof T]: keyof Pick<T, K> }
其次是一个简单的接口与自定义类型的使用方法:
interface MyInterface {
a: string;
b: string;
}
当我喜欢的类型的变量是一类外定义,打字稿是幸福的:
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('');
}
为什么打字稿报告member
的派生类作为错误的执行情况时它的工作原理类外,当它不被标记为抽象的?
类成员的类型,而不考虑什么是在基类,然后才是派生类检查与所述基类的相容性。由于成员是基于初始化值类型的,打字稿不会使用文字类型属性类型(有的只是某些地方TS不会扩大文字类型,这是不是其中之一)
最好认为你可以做的是使用该成员的显式类型注解,你已经说你在你的问题的尝试:
class DerivedClass extends BaseClass<MyInterface> {
protected member: KeyMap<MyInterface> = {
a: 'a',
b: 'b'
};
protected method = () => console.log('');
}