首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将类型信息从父类拉到子类

将类型信息从父类拉到子类
EN

Stack Overflow用户
提问于 2021-01-27 07:19:02
回答 1查看 87关注 0票数 1

假设我有这个基类

代码语言:javascript
复制
class BaseComponent<T> {
    constructor(protected selectors: T) {}
}

LoginComponent.ts

代码语言:javascript
复制
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);

多亏了typeof ADMIN_SELECTORS,我告诉TypeScript,this.selectors的结构将是什么。这使我在使用this.selectors时可以自动完成和打字。

代码语言:javascript
复制
get userInput() {
        return this.selectors.inputUser; // Property 'inputUser' does not exist on type '{ inputUserName: string; buttonLogin: string; textError: string; }'
    }

好的!

但是,我现在需要做的是创建一个子类CustomerLoginComponent。这个子类对于inputUserName和它的选择器对象中名为textCustomerName的新的唯一属性应该有不同的值。

CustomerLoginComponent.ts

代码语言:javascript
复制
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);

我在这里遇到的错误是代码的这一部分中的Property 'textCustomerName' does not exist on type '{ inputUserName: string; buttonLogin: string; textError: string; }'

代码语言:javascript
复制
 get customerName() {
        return this.selectors.textCustomerName;
    }

我决定要做的是调整LoginComponent

代码语言:javascript
复制
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;
    }
}

现在,当我尝试使用CustomerLoginComponent时,没有错误。

但是,我现在想不出的是如何用CustomerLoginComponentCustomerLoginComponent进行注释。基本上,TypeScript的建议是这样做:

代码语言:javascript
复制
class CustomerLoginComponent extends LoginComponent<typeof CUSTOMER_SELECTORS> {
    constructor(selectors: { inputUserName: string; buttonLogin: string; textError: string; } & { inputUserName: string; textCustomerName: string; }) {
        super(selectors);
    }
}

当然,我不能硬编码对象结构,因为它是一种“灵活”的对象(这就是我使用typeof__的原因)。另外,它还位于另一个文件中。

我的问题是,我能否让CustomerLoginComponent知道selectors的类型是两个合并的对象:

父类(我想应该以某种方式传递的类型)+ typeof CUSTOMER_SELECTORS

我试着理解infer关键字,但我不确定这是我要找的.另外,我也不太确定这部分:

代码语言:javascript
复制
class LoginComponent<T> extends BaseComponent<typeof ADMIN_SELECTORS> {
    constructor(protected selectors: typeof ADMIN_SELECTORS & T) {
    }
}

我想我的基类犯了个错误

代码语言:javascript
复制
class BaseComponent<T> {
    constructor(protected selectors: T) {}
}

由于我仍然必须显式地将LoginComponent中的选择器类型注释为: typeof ADMIN_SELECTORS,否则它将无法工作。

总之,正如您可能猜到的,上面的示例在设计中存在一些核心问题,因此,任何帮助都将不胜感激。

否则,我想知道如何在CustomerLoginComponent中注释选择器参数的类型。

EN

回答 1

Stack Overflow用户

发布于 2021-01-30 00:35:43

仿制药

你几乎和typeof ADMIN_SELECTORS & T在一起了。我认为您对BaseComponentLoginComponent中的两个不同的LoginComponent泛型感到困惑,它们代表着不同的事物。TBaseComponent中表示所有的选择器。LoginComponent知道它的选择器是typeof ADMIN_SELECTORS类型,所以它需要泛型的唯一原因是处理子类添加的附加属性。

T可以表示那些附加的选择器:

代码语言:javascript
复制
class LoginComponent<T = {}> extends BaseComponent<typeof ADMIN_SELECTORS & T> {

或者T可以表示所有选择器:

代码语言:javascript
复制
class LoginComponent<T extends typeof ADMIN_SELECTORS = typeof ADMIN_SELECTORS> extends BaseComponent<T> {

在这两种情况下,我都为T设置了一个默认值,以便它永远不是unknown

构造器参数

现在我们来讨论哪些参数需要传递给构造函数,以及它们是什么类型。在所有三个类中,构造函数接受整个selectors对象。

这意味着您不能调用new CustomerLoginComponent(CUSTOMER_SELECTORS),因为您没有提供LoginComponent所需的管理选择器。你必须打电话给new CustomerLoginComponent({...ADMIN_SELECTORS, ...CUSTOMER_SELECTORS})

如果您不想这样做,我们需要使类从常量中获得选择器,而不是通过构造函数。通常来说,让class如此紧密地耦合到其数据并不是一个好主意,但是通过让类型依赖于typeof (常量),您已经在紧密耦合它。

代码语言:javascript
复制
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();
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65914503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档