我正在尝试让智能感知与通用类型的接口(interface)一起工作,我希望智能感知和 typescript 检查能够为子级的属性工作,但我不知道如何编写我的界面。
这是我正在尝试做的事情的一个非常简单的示例
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's Bar,并且它们都具有更多的属性),我希望能够使用所选的键来生成类似的内容
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 中选择的有效值。
最佳答案
这无法通过单步对象赋值来完成 - 无法根据对象初始化中其他属性的值来限制对象属性的类型。
但语法略有不同,这是可能的:
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")[]; })[]
关于Typescript - 根据给定键确定子对象的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48190124/