简体   繁体   English

Typescript 初始化 object 与通用

[英]Typescript init object with generic

What I want is something like this:我想要的是这样的:

class ThemeExample <T> {
    static theme : T;
    static init(theme : T){
        ThemeExample.theme = theme;
    }
};

//config it 
ThemeExample.init({
    hello : 'hi'
})
//in another file access properties with auto completion
ThemeExample.theme.hello

But this doesn't work.但这不起作用。 TS2302: Static members cannot reference class type parameters.

Tried a few other things such as making the class in a function and return it, and use functions generic in the class.尝试了其他一些方法,例如在 function 中制作 class 并返回它,并使用 class 中的通用函数。 Still couldn't find a way that would let me initialize this config once.仍然找不到让我初始化此配置一次的方法。 And then access the theme later and get auto completion for all its properties in other files.然后稍后访问主题并自动完成其他文件中的所有属性。 I need something like this please help me, I'm too frustrated.我需要这样的东西请帮助我,我太沮丧了。

The static side of a class consists of the class constructor, and there is exactly one such constructor. class 的class端由 class 构造函数组成,并且只有一个这样的构造函数。 It has no access to any generic parameters on the instance type, because a class constructor needs to be able to create instances for any possible specification of that generic parameter.它无法访问实例类型上的任何泛型参数,因为 class 构造函数需要能够为该泛型参数的任何可能规范创建实例。 In your ThemeExample<T> code, the class constructor must be able to make instances of, say, ThemeExample<string> and ThemeExample<number> .在您的ThemeExample<T>代码中,class 构造函数必须能够创建ThemeExample<string>ThemeExample<number>的实例。 If you could have a static property of type T , it would mean that it would have to be both a string and a number and any other possible type for T .如果您可以拥有T类型的 static 属性,则意味着它必须stringnumber以及T的任何其他可能类型。 It doesn't work.它不起作用。

Conceptually you could imagine ThemeExample as having a static property named theme of type unknown , and then when you call ThemeExample.init("hello") , the compiler would narrow the ThemeExample class constructor so that theme is now of type string instead of unknown .从概念上讲,您可以将ThemeExample想象为具有名为theme类型为unknownstatic属性,然后当您调用ThemeExample.init("hello")时,编译器将 缩小ThemeExample class 构造函数的范围,以便theme现在是string类型而不是unknown类型。 But there is no good mechanism to do this.但是没有很好的机制来做到这一点。 You could imagine writing something like an assertion function which would have such an effect:您可以想象编写类似断言 function的东西,它会产生这样的效果:

interface ThemeExampleConstructor<T = unknown> {
  theme: T;
  init<T>(theme: T): asserts this is ThemeExampleConstructor<T>;
  new(): ThemeExample<T>;
}

declare const ThemeExample: ThemeExampleConstructor;

ThemeExample.theme.toUpperCase(); // error
ThemeExample.init("hello");
ThemeExample.theme.toUpperCase(); // okay
new ThemeExample().instanceProp.toUpperCase(); // okay

But you can't do it with class syntax, and even if you got this done, narrowing like this doesn't work across file boundaries or even function boundaries.但是你不能用class语法来做到这一点,即使你完成了这个,像这样的缩小也不能跨越文件边界甚至 function 边界。 There's no mechanism whereby the compiler would see that ThemeExample.init("hello") in one file happens before the ThemeExample.theme.toUpperCase() in another file.没有任何机制可以让编译器看到一个文件中的ThemeExample.init("hello")发生在另一个文件中的ThemeExample.theme.toUpperCase()之前 So we can't do this at all.所以我们根本不能这样做。


Instead I'd suggest going the route of a factory function which produces new class constructors.相反,我建议走工厂 function 的路线,该工厂生产新的 class 构造函数。 This function would exist in some library, say Library/index.ts :这个 function 将存在于某些库中,例如Library/index.ts

export function initThemeExample<T>(theme: T) {
    return class ThemeExample {
        static theme = theme;
    };
}

Then in another file like userLib.ts , a user could import that from the library, configure, and re-export:然后在userLib.ts类的另一个文件中,用户可以从库中import该文件,配置并重新导出:

import {initThemeExample} from './Library'

//config it 
export const ThemeExample = initThemeExample({
    hello: 'hi'
})

And then the user could use this configured constructor in all other files:然后用户可以在所有其他文件中使用这个配置的构造函数:

import {ThemeExample} from './userLib'

//import your ThemeExaple in another file
document.write(ThemeExample.theme.hello.toUpperCase()); // HI

Link to StackBlitz code 链接到 StackBlitz 代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM