0

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

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 
    } 
} 

回答

0

这个怎么样?

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>) { 
    // ... 
    } 
} 

我取得了一些地方的变化:

  • 使用T代替this在setMetadata的类型
  • 不setMetadata的第二个参数类型使用keyof
  • 招富到一个单独的我自己USI类
+0

谢谢您的答复。不幸的是,使用继承不是一种选择 - “configure”方法将在类中定义,该类将成为拥有foo属性的类的父类。它是面向客户端的API的一部分,我希望尽可能简单。 – Tom

+0

你居然打算'美孚'是空的,希望利用它只是在setMetadata约束型PARAMS?由于TypeScript的结构类型本质,这是行不通的。一个空的界面将接受任何东西。你将不得不使用特殊标记字段来填充类实例或容器对象中的字段,以便能够执行此操作。或者,也许你可以用装饰器做些事情(我没有用过它们,所以不能评论)。 – dbandstra

+0

你说得对。我以不同的方式(功能)解决它,请参阅我自己的答案。不幸的是,装饰者不会解决问题。感谢您的时间和精力。 – Tom

0

解决它纳克功能:

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