基于泛型参数定义类属性

时间:2018-02-07 01:18:44

标签: typescript generics

class Component { }
class ShallowWrapper { }

// generic P is a simple object
class TestContainer<T extends Component, P extends object> 
{
    constructor(reactElement: T, selectors: P) {
        // iterate over selectors and define object properties
    }
    initialize(): void { }
    [elem: keyof P]: any 
    // I need to define class properties based on P's keys
    // -- compiler throws --
    // An index signature parameter type cannot be a union type. 
    // Consider using a mapped object type instead.
}

const p = new TestContainer(new Component, { test: 'a' });

const v = p.test // this throws a type error (property does not exist)

在上面的代码中,我尝试基于泛型参数P动态定义对象属性。但是编译器抛出错误

  

索引签名参数类型不能是联合类型。考虑   改为使用映射的对象类型。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

编译器会为您提供此错误,因为您尝试将索引签名参数的语法与映射类型的语法混合使用。索引签名参数可能只有stringnumber类型。

您可以使用工厂方法通过强类型实现您想要的效果:

class Component { }

class TestContainer<T extends Component> {
    static create<T extends Component, P extends object>(reactElement: T, selectors: P) {
        return Object.assign(new TestContainer(reactElement), selectors);
    }

    private constructor(reactElement: T) {}
}

const p = TestContainer.create(new Component(), { test: 'a' });

const v = p.test;

顺便说一下,我不知道你是否将Component弄空了以便插图,但是你绝不应该使用空类来限制类型。由于TypeScript使用结构类型系统,因此空类在结构上等同于Object。这意味着T extends Component基本上没用,因为它与T extends Object相同,后者又与T相同。如果您尝试它,您将看到以下内容有效:

TestContainer.create(42, { test: 'a' })