简体   繁体   English

Typescript 使用映射类型与 arrays

[英]Typescript using mapped types with arrays

I'm trying to use mapped types with typescript, which is supposed to be possible, but running into some issues.我正在尝试将映射类型与 typescript 一起使用,这应该是可能的,但遇到了一些问题。

Let's say I have 3 classes:假设我有 3 个课程:

class A {
    public foo1 = 1;
}
class B {
    public foo2 = 1;
}
class C {
    public foo3 = 1;
}

const base = [A, B, C] as const;

Basically, what I want is to pass base into some function, and get back an array with 3 matching instances.基本上,我想要的是将base传递给一些 function,并取回一个包含 3 个匹配实例的数组。

type CTOR = new(...args: any[]) => any

function instantiate1<T extends ReadonlyArray<CTOR>>(arr: T): {[K in keyof T]: T[K]} {
    const items = arr.map(ctor => new ctor());
    return items as any; //Don't mind about breaking type safety inside the function
}

Now this returns:现在返回:

const result1 = instantiate2(base) //type is [typeof A, typeof B, typeof C]

which makes sense, as I didn't really "map" the type yet, just made sure the syntax works.这是有道理的,因为我还没有真正“映射”类型,只是确保语法有效。

However if I try to actually map the type:但是,如果我尝试实际 map 类型:

function instantiate2<T extends ReadonlyArray<CTOR>>(arr: T): {[K in keyof T]: InstanceType<T[K]>} {
    const items = arr.map(ctor => new ctor());
    return items as any; //Don't mind about breaking type safety inside the function
}

I get an error that T[K] doesn't satisfy the constraint of instance type.我收到T[K]不满足实例类型约束的错误。

anyone as an idea for a workaround?任何人作为解决方法的想法?

full playground link 完整的游乐场链接

This is a known bug in TypeScript, according to microsoft/Typescript#27995 .根据microsoft/Typescript#27995 ,这是 TypeScript 中的一个已知错误。 It's a fairly old issue now and is on the "Backlog", so I wouldn't expect it to be fixed anytime soon.这是一个相当老的问题,并且在“积压”中,所以我不希望它很快得到修复。


Workarounds:解决方法:

Explicitly constrain T[K] to the desired constructor type.T[K]显式约束为所需的构造函数类型。 I usually do this with the Extract<T, U> utility type like this:我通常使用Extract<T, U>实用程序类型来执行此操作,如下所示:

declare function instantiate<T extends ReadonlyArray<Ctor>>(arr: T): {
    [K in keyof T]: InstanceType<Extract<T[K], Ctor>>
};

const result = instantiate(base);
// const result: readonly [A, B, C]

Or, you could replace the InstanceType<T> utility type with your own version that doesn't care if T is a constructor.或者,您可以将InstanceType<T>实用程序类型替换为您自己的版本,该版本不关心T是否是构造函数。 The existing type definition is: 现有的类型定义是:

type InstanceType<T extends new (...args: any) => any> = 
   T extends new (...args: any) => infer R ? R : any;

So you can loosen it to:因此,您可以将其放松为:

type MyInstanceType<T> = // no constraint on T
    T extends new (...args: any) => infer R ? R : any;

and then your original version works as expected:然后您的原始版本按预期工作:

declare function instantiate<T extends ReadonlyArray<Ctor>>(arr: T): {
    [K in keyof T]: MyInstanceType<T[K]>
};

const result = instantiate(base);
// const result: readonly [A, B, C]

Playground link to code Playground 代码链接

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

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