【问题标题】:Define class properties based on generic parameter基于泛型参数定义类属性
【发布时间】:2018-02-07 15:09:03
【问题描述】:
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 动态定义对象属性。但是编译器会抛出错误

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

我该如何解决这个问题?

【问题讨论】:

    标签: typescript generics


    【解决方案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 又与T 相同。如果您尝试一下,您会发现以下内容是有效的:

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

    【讨论】:

    • 感谢这项工作。我最终实现了类似的东西。该组件只是为了说明:)
    猜你喜欢
    • 2021-03-26
    • 2020-03-22
    • 1970-01-01
    • 2019-05-04
    • 2020-07-04
    • 2019-12-28
    • 2015-11-18
    • 1970-01-01
    • 2019-08-12
    相关资源
    最近更新 更多