在Typescript中将类名映射到相应的类实例。

huangapple go评论49阅读模式
英文:

Mapping class names against corresponding class instances in Typescript

问题

type Instances = {
    [K in keyof typeof arr[number] as Uncapitalize<K>]: InstanceType<typeof arr[number][K]>;
};
英文:

In a Typescript project that I'm working on, there are a ton of classes that share the same constructor definition. Instead of initializing them line by line, I thought about storing the classes inside an array, and then loop through it to initialize all of them like so:

class A { ... }
class B { ... }

const arr = [A, B];
const instances: ___ = {};

arr.forEach((Class) =&gt; {
    instances[uncapitalize(Class.name)] = new Class();
});

function uncapitalize&lt;T extends string&gt;(str: T): Uncapitalize&lt;T&gt; {
    ...
}

Right now, I'm having trouble coming up with a type declaration for instances that would map 'uncapitalized' class names to their corresponding instances.

I've tried the following as a type declaration for instances:

[K in typeof arr[number][&#39;name&#39;] as `${Uncapitalize&lt;K&gt;}`]: InstanceType&lt;typeof arr[number]&gt;

but this type declaration would allow any instance to be assigned to any class name key. Also, Typescript intellisense isn't picking up on the properties of instances for some reason.

答案1

得分: 1

类本身在TS中没有名称:

class A { #private = true }
A.name
// ^?
// (property) Function.name: string

所以你需要使用类的记录而不是数组来保持它们的名称:

class A { #private = true }
class B { #private = true }
function uncapitalize<T extends string>(str: T): Uncapitalize<T> {
    return str.toLowerCase() as any;
}

const classMap = { A, B };
// 满足Record<string, new () => object>;如果你想检查它们
const instances: {
    [K in keyof typeof classMap as Uncapitalize<K>]: InstanceType<typeof classMap[K]>
} = Object.fromEntries(
    Object.entries(classMap)
        .map(([k, v]) => [uncapitalize(k), new v()])
) as any;
// const instances: {
//     a: A;
//     b: B;
// }

注意:这只是代码的翻译部分,没有其他内容。

英文:

Classes themselves don't have names in TS:

class A { #private = true }
A.name
// ^?
// (property) Function.name: string

so you need a Record of classes rather then array to keep their names:

class A { #private = true }
class B { #private = true }
function uncapitalize&lt;T extends string&gt;(str: T): Uncapitalize&lt;T&gt; {
    return str.toLowerCase() as any;
}

const classMap = { A, B };
// satisfies Record&lt;string, new () =&gt; object&gt;; if you want to check them
const instances: {
    [K in keyof typeof classMap as Uncapitalize&lt;K&gt;]: InstanceType&lt;typeof classMap[K]&gt;
} = Object.fromEntries(
    Object.entries(classMap)
        .map(([k, v]) =&gt; [uncapitalize(k), new v()])
) as any;
// const instances: {
//     a: A;
//     b: B;
// }

huangapple
  • 本文由 发表于 2023年7月3日 02:06:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76600198.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定