我试图让Intellisense使用泛型类型的界面,我喜欢智能感知和打字稿检查以适应孩子的属性,但我无法弄清楚如何写我的界面。
这是我尝试做的一个非常简单的例子
interface Foo1 {
prop1: string;
prop2: boolean;
}
interface Foo2 {
prop3: string;
prop4: boolean;
}
interface Bar1 {
thing1: Foo1;
thing2: Foo2;
}
interface Bar2 {
thing3: Foo1;
thing4: Foo2;
}
鉴于这样的结构(在我的项目中有更多的Foo&#39;并且它们都具有更多属性)我希望能够使用所选择的键来生成这样的结构< / p>
interface TestItem<T> {
field: keyof T; //This will be a key of a Bar object
select: (keyof T[keyof T])[]; //This is trying to state that elements in this array must be a property of Bar[field], e.g if field is "thing1" the only valid elements would be "prop1" or "prop2"
}
interface TestObject<T> {
itemArray: TestItem<T>[];
}
let test: TestObject<Bar1> = {
itemArray: [
{
field: "thing1",
select: ["prop1"] //error: string is not assignable to type never
}, {
field: "thing2",
select: ["prop3"] //error: string is not assignable to type never
}
]
}
我没想到这会起作用,但我已经尝试了很多事情而没有更好的结果。我知道我可以添加更多GenericType参数并指定传递给每个TestItem的内容,但是我希望有人知道指定字段的方式足以让Typescript在TestItem中计算select的有效值。
答案 0 :(得分:1)
无法通过单步对象分配完成 - 无法根据对象初始化中其他属性的值来限制对象属性的类型。
但语法略有不同,可能:
class TestObject<T> {
itemArray: { field: keyof T, select: string[] }[];
// no constraint could be specified for select here
// because there is not enough information about T here
// but we can define a function that will apply constraint
// when called from a subclass
testItem<K extends keyof T>(item: { field: K, select: (keyof T[K])[] }) {
return item
}
}
class TestBar1 extends TestObject<Bar1> {
itemArray = [
this.testItem({ field: "thing1", select: ["prop1"] }), // ok
this.testItem({ field: "thing2", select: ["prop3"] }), // ok
this.testItem({ field: "thing1", select: ["prop3"] }) // error:
// Argument of type '{ field: "thing1"; select: "prop3"[]; }'is not assignable
// to parameter of type '{ field: "thing1"; select: ("prop1" | "prop2")[]; }'.
// Types of property 'select' are incompatible.
// Type '"prop3"[]' is not assignable to type '("prop1" | "prop2")[]'.
// Type '"prop3"' is not assignable to type '"prop1" | "prop2"'.
]
}
let test = new TestBar1().itemArray;
删除错误的项目后,推断test
的类型符合预期:
({ field: "thing1"; select: ("prop1" | "prop2")[]; }
| { field: "thing2"; select: ("prop3" | "prop4")[]; })[]
答案 1 :(得分:0)
我不太确定我是否正确理解了您的问题,但这有效:
interface Foo1 {
prop1: string;
prop2: boolean;
}
interface Foo2 {
prop3: string;
prop4: boolean;
}
interface Bar1 {
thing1: Foo1;
thing2: Foo2;
}
interface Bar2 {
thing3: Foo1;
thing4: Foo2;
}
interface TestItem<T, K> {
field: keyof T;
select: (keyof K)[]; //This keyof T being the same as field
}
interface TestObject<T, K> {
itemArray: TestItem<T, K>[];
}
let test: TestObject<Bar1, Foo1> = {
itemArray: [
{
field: "thing1",
select: ["prop1"]
}, {
field: "thing2",
select: ["prop2"]
}
]
}
您的示例无效,因为prop1
和prop2
都不归Bar1
所有,因此您必须将您的通用扩展另一个(使用K
这里)