如何向 TypesScript 类添加动态属性并保持正确的类型

编程入门 行业动态 更新时间:2024-10-28 02:28:34
本文介绍了如何向 TypesScript 类添加动态属性并保持正确的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送ChatGPT账号..

我有一个从文件 Users.ts

    export default class Users {}

然后我从另一个文件index.ts导出Users.ts:

I am then exporting Users.ts from another file, index.ts:

    // classes
    export {default as Users} from './Users'

我有第三个文件 Foo.ts,我想在其中动态实例化从 index.ts 导出的所有类,并将它们作为属性添加到该类中:

I have a third file, Foo.ts, where I want to dynamically instantiate all the exported classes from index.ts and add them as properties to that class:

    import * as classes from './index'

    class Foo {
        constructor() {
           const httpClient = new HttpClient()
        }

        _addClasses() {
           for (const class in classes) {
             this[class] = new classes[class](this.httpClient);
           }
        }
    }

我的问题是,如何将正确的类型添加到 Foo,以便我可以在 IDE 中为 .users 获得正确的自动完成功能,例如:

My question is, how can I add the correct types to Foo, so that I can get the correct autocompletion in the IDE for .users like:

new Foo(new HttpClient).users

推荐答案

这个问题的第一部分是创建一个包含导入模块的实例类型的新类型.为此,我们将使用预定义的条件类型 InstanceType 来提取类的实例类型.要获取模块的类型,我们将使用 typeof classes.将它全部包装在一个映射类型中,我们得到:

The first part of this question is to create a new type that contains the instance types of the imported module. To do this, we will use the predefined conditional type InstanceType to extract the instance type of a class. To get the type of the module we will use typeof classes. Wrap it all in a mapped type and we get:

type ClassInstances = {
    [P in keyof typeof classes]: InstanceType<typeof classes[P]>
}

// For the example above this is equivalent to 
type ClassInstances = {
    Users: classes.Users;
}

现在我们需要将这些新属性放入类中.要做到这一点而不显式定义它们,我们可以使用一个空类表达式作为 Foo 的基类,并断言这个空类返回的实例具有这些成员(实际上并没有,但我们以及 _addClasses 中的这些成员,所以一切都解决了).综合起来,我们得到:

Now we need to get these new properties into the class. To do this without defining them explicitly, we can use an empty class expression as the base class for Foo and assert that the instance returned by this empty class has those members (it doesn't really, but we and these members in _addClasses so it all works out). Putting it all together we get:

import * as classes from './index';

type ClassInstances = {
    [P in keyof typeof classes]: InstanceType<typeof classes[P]>
}

class Foo extends (class {} as new () => ClassInstances) {
    httpClient: HttpClient;
    constructor() {
        super();
        this.httpClient = new HttpClient()
        this._addClasses();
    }

    _addClasses() {
        for (const cls of Object.keys(classes) as Array<keyof typeof classes>) {
            this[cls] = new classes[cls](this.httpClient);
        }
    }
}

new Foo().Users // ok now name is the same as the name used in the export in index.ts so it's upper case. No string manipulation on string properties.

这篇关于如何向 TypesScript 类添加动态属性并保持正确的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

更多推荐

[db:关键词]

本文发布于:2023-04-29 09:36:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1187996.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:属性   正确   类型   动态   TypesScript

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!