使用参数的属性作为打字稿中的类型

时间:2020-08-18 13:32:44

标签: javascript typescript types

我想为依赖于参数传递的属性的类的属性分配类型。我想知道是否有可能。

示例:

enum MyEnum {
    g,
    f,
    h,
}

interface MappedTypes {
    [MyEnum.f]: X
    [MyEnum.g]: Y
    [MyEnum.h]: Z
}

class MyClass {
    a: string // does not matter
    b: something like MappedTypes[c]
    c: MyEnum

    constructor(params: { a: string; b: MappedTypes[<inherit from c>]; c: MyType }) {
        // for example
        // if c === MyEnum.g
        // b must be Y as mapped in MappedTypes  
    }
}

1 个答案:

答案 0 :(得分:2)

您可以做的一件事是在E中将类generic设置为c属性的类型,并给b一个lookup type,例如{ {1}}。这是我现在所写代码中最接近的代码:

MappedTypes[E]

请注意,一旦使用了类似的泛型,您可能会发现在class MyClass<E extends MyEnum> { a: string b: MappedTypes[E] c: E constructor(params: { a: string; b: MappedTypes[E]; c: E }) { this.a = params.a; this.b = params.b; this.c = params.c } } 的实现中很难以关联的方式使用MyClassb。有关更多信息,请参见microsoft/TypeScript#13995


进行此操作的另一种方法是将cb捆绑成discriminated union类型的单个c属性,如下所示:

params

如果您检查type Params = { [K in MyEnum]: { a: string, b: MappedTypes[K], c: K } }[MyEnum] ,则会发现它的计算结果为以下并集:

Params

然后您可以像这样定义/* type Params = { a: string; b: Y; c: MyEnum.g; } | { a: string; b: X; c: MyEnum.f; } | { a: string; b: Z; c: MyEnum.h; } */

MyClass

因此,您需要引用class MyClassU { constructor(public params: Params) { } } 而不是this.b,这可能很烦人。从好的方面来说,您将可以在this.params.b上进行类似switch的操作,并且编译器将了解它与this.params.c的类型有关:

this.params.b

好的,希望其中之一能有所帮助;祝你好运!

Playground link to code