【问题标题】:Constrain keys that are part of looked-up type作为查找类型的一部分的约束键
【发布时间】:2017-05-30 17:18:22
【问题描述】:

我需要创建一个约束,将keyof 关键字列出的TP1 的键限制为特定类型的属性。当我使用builder.setMetadata 方法时,第一个参数不应该接受字符串“configure”作为有效值(它应该接受foo 和其他键入为Foo<something> 的键)。我试图自己想出一个解决方案,但我有点迷茫,现在已经做了三个多小时。以下是工作代码:

interface Foo<T> {};

class Test { prop: string; }

class Builder<T> {
    public setMetadata<TP1 extends keyof this, TP2 extends keyof this[TP1]>(prop: TP1, propOfProp: TP2) {
        // ...
    }
}

class Bar {
    foo: Foo<Test>;

    configure(builder: Builder<Bar>) {
        builder.setMetadata("", ""); // only "foo" should be accepted value in the first argument, "configure" shouldn't be in the list
    }
}

【问题讨论】:

    标签: typescript types algebraic-data-types complex-data-types


    【解决方案1】:

    这个怎么样?

    class Builder<T> {
      public setMetadata<TP1 extends keyof T, TP2 extends T[TP1]>(prop: TP1, propOfProp: TP2) {
        // ...
      }
    }
    
    class BarData {
      foo: Foo<Test>;
    }
    
    class Bar extends BarData {
      configure(builder: Builder<BarData>) {
        // ...
      }
    }
    

    我在几个地方做了修改:

    • 在 setMetadata 的类型中使用 T 而不是 this
    • 不要在 setMetadata 的第二个参数类型中使用keyof
    • 将 foo 移到单独的类中

    【讨论】:

    • 感谢您的回复。不幸的是,使用继承不是一种选择——configure 方法将在一个类中定义,该类将成为拥有 foo 属性的类的父类。它是面向客户端的 API 的一部分,我希望它尽可能简单。
    • 您是否真的打算将Foo&lt;T&gt; 设为空,希望仅将其用于限制 setMetadata 中的类型参数?由于 TypeScript 的结构类型特性,这将不起作用。一个空的接口可以接受任何东西。您必须使用特殊标记字段将类实例或容器对象中的字段装箱才能执行此操作。或者也许你可以用装饰器做点什么(我没用过,所以不能评论)。
    • 你是对的。我以不同的方式(功能)解决了它,请参阅我自己的答案。不幸的是,装饰者不会解决这个问题。感谢您的时间和精力。
    【解决方案2】:

    自己用函数解决了:

    function createInstance<T extends Function & { [P in keyof TSchema]: Foo<any> }>(schema: T, configure: (builder: Builder<T["prototype"]>) => void): any {
        // ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多