Typescript 将类型信息从父类拉到子类
假设我有一个基类Typescript 将类型信息从父类拉到子类,typescript,generics,Typescript,Generics,假设我有一个基类 class BaseComponent<T> { constructor(protected selectors: T) {} } 很好 但是,我现在需要做的是创建一个子类CustomerLoginComponent。 该子类的选择器对象中名为textCustomerName的新唯一属性上的inputUserNameplus应有不同的值 CustomerLoginComponent.ts const ADMIN_SELECTORS = { inpu
class BaseComponent<T> {
constructor(protected selectors: T) {}
}
很好
但是,我现在需要做的是创建一个子类CustomerLoginComponent
。
该子类的选择器对象中名为textCustomerName
的新唯一属性上的inputUserName
plus应有不同的值
CustomerLoginComponent.ts
const ADMIN_SELECTORS = {
inputUserName: "foo",
buttonLogin: "bar",
textError: "baz",
};
class LoginComponent<T> extends BaseComponent<typeof ADMIN_SELECTORS> {
constructor(protected selectors: typeof ADMIN_SELECTORS) {
super(selectors);
}
get loginButton() {
return this.selectors.buttonLogin;
}
}
// EXAMPLE CALL
const login = new LoginComponent(ADMIN_SELECTORS);
const CUSTOMER_SELECTORS = {
inputUserName: "abc",
textCustomerName: "xyz",
};
class CustomerLoginComponent extends LoginComponent<typeof CUSTOMER_SELECTORS> {
constructor(selectors) {
super(selectors);
}
get customerName() {
return this.selectors.textCustomerName;
}
}
// EXAMPLE CALL
const customerLogin = new CustomerLoginComponent(CUSTOMER_SELECTORS);
我决定做的是调整LoginComponent
:
class LoginComponent<T> extends BaseComponent<typeof ADMIN_SELECTORS> {
constructor(protected selectors: typeof ADMIN_SELECTORS & T) { // Note ' & T'!
super(selectors);
}
get loginButton() {
return this.selectors.buttonLogin;
}
}
当然,我不能硬编码对象结构,因为它是一种“灵活”的对象(这就是为什么我使用typeof
)。另外,它位于另一个文件中
我的问题是,我能否让CustomerLoginComponent
知道选择器的类型是两个合并对象:
父类中的一个(我想我应该以某种方式传递它的类型?+typeofcustomer\u选择器
)
我试图理解推断
关键字,但我不确定我要找的是什么。。。
此外,我对这一部分也不是很确定:
class LoginComponent<T> extends BaseComponent<typeof ADMIN_SELECTORS> {
constructor(protected selectors: typeof ADMIN_SELECTORS & T) {
}
}
classlogincomponent扩展了BaseComponent{
构造函数(受保护的选择器:管理员类型\u选择器&T){
}
}
我想我的基础班错了
class BaseComponent<T> {
constructor(protected selectors: T) {}
}
类基本组件{
构造函数(受保护的选择器:T){}
}
由于我仍然必须将LoginComponent
中的选择器类型显式注释为:typeof ADMIN\u selectors
,否则它将无法工作
总而言之,正如您可能猜到的那样,上面的示例在设计中有一些核心问题,因此任何帮助都将不胜感激
否则,我想知道如何在CustomerLoginComponent
泛型中注释选择器参数的类型
使用类型的管理员选择器&T
,您就快到了。我想您会被BaseComponent
和LoginComponent
中代表不同事物的两个不同的T
泛型弄糊涂了<BaseComponent
中的code>T
表示所有选择器LoginComponent
知道它的选择器是typetypeof ADMIN\u选择器
,所以它需要是泛型的唯一原因是处理由子类添加的附加属性
T
可以仅代表这些附加选择器:
class LoginComponent<T = {}> extends BaseComponent<typeof ADMIN_SELECTORS & T> {
class LoginComponent<T extends typeof ADMIN_SELECTORS = typeof ADMIN_SELECTORS> extends BaseComponent<T> {
在这两种情况下,我都为T
设置了一个默认值,这样它就永远不会未知
构造函数参数
现在我们来讨论需要传递给构造函数的参数以及它们的类型。在所有三个类中,构造函数接受整个选择器
对象
这意味着您不能调用new CustomerLoginComponent(客户选择器)
,因为您没有提供LoginComponent
所需的管理员选择器。您必须调用新的CustomerLoginComponent({…ADMIN\u SELECTORS,…CUSTOMER\u SELECTORS})
如果您不想这样做,我们需要这样做,以便类从常量而不是通过构造函数获取选择器。让类与数据紧密耦合通常不是一个好主意,但是通过让键入依赖于常量的类型,您已经将其紧密耦合了
class BaseComponent<T> {
constructor(protected selectors: T) {}
}
class LoginComponent<Extra = {}> extends BaseComponent<typeof ADMIN_SELECTORS & Extra> {
constructor(extraSelectors: Extra = {} as any) { // the typing here is not ideal because I wanted to make the extras optional
super({...extraSelectors, ...ADMIN_SELECTORS});
}
}
class CustomerLoginComponent extends LoginComponent<typeof CUSTOMER_SELECTORS> {
constructor() {
super(CUSTOMER_SELECTORS);
}
}
// EXAMPLE CALL
const login = new LoginComponent();
const customerLogin = new CustomerLoginComponent();
类基本组件{
构造函数(受保护的选择器:T){}
}
类LoginComponent扩展了BaseComponent{
构造函数(extraSelectors:Extra={}与任何构造函数一样){//这里的类型并不理想,因为我想让extras成为可选的
超级({…外部选择器,…管理员选择器});
}
}
类CustomerLoginComponent扩展了LoginComponent{
构造函数(){
超级(客户选择);
}
}
//示例调用
const login=new LoginComponent();
const customerLogin=new CustomerLoginComponent();
我假设您已经知道这一点,但如果您不知道,当您只调用super(…args)
时,您可以省略构造函数。如果这不仅仅是一个示例,那么我建议删除这些选项,以避免与类型匹配出现任何问题。@101arrowz您会惊讶于我所知甚少:)您不介意发布一个答案来说明这一点吗?我不太明白这个意思
class LoginComponent<T = {}> extends BaseComponent<typeof ADMIN_SELECTORS & T> {
class LoginComponent<T extends typeof ADMIN_SELECTORS = typeof ADMIN_SELECTORS> extends BaseComponent<T> {
class BaseComponent<T> {
constructor(protected selectors: T) {}
}
class LoginComponent<Extra = {}> extends BaseComponent<typeof ADMIN_SELECTORS & Extra> {
constructor(extraSelectors: Extra = {} as any) { // the typing here is not ideal because I wanted to make the extras optional
super({...extraSelectors, ...ADMIN_SELECTORS});
}
}
class CustomerLoginComponent extends LoginComponent<typeof CUSTOMER_SELECTORS> {
constructor() {
super(CUSTOMER_SELECTORS);
}
}
// EXAMPLE CALL
const login = new LoginComponent();
const customerLogin = new CustomerLoginComponent();