打字稿创建一个类型,其属性是接口的属性
Typescript Create a type whose properties are the properties of an interface
我有一个接口定义如下
export interface RoutingMap {
ticket: {
id: number
},
car: {
model: string,
make: number
}
}
我希望能够为对象创建一个接口,该对象具有 2 个属性 - 一个是 RoutingMap
中的键,另一个是 Key
中的任何类型RoutingMap
是。
在伪代码中我想象它看起来像这样
export interface RoutingMessage {
resource: keyof RoutingMap,
params: RoutingMap["resource"]
}
我的最终目标是能够构建这样的对象
const msg: RoutingMessage = {
resource: "ticket",
params: { id: 10 }
}
const invalidMsg: RoutingMessage = {
resource: "something", //TS error - "something" is not a key of routing map
params: { id: 10 }
}
const invalidMsg2: RoutingMessage = {
resource: "car"
params: { model: "tesla", make: true } //TS error - "make" is not a boolean
}
const invalidMsg3: RoutingMessage = {
resource: "car"
params: { id: 123 } //TS error - id is not assinable to {model: string, make: boolean}
}
RoutingMap
会随着时间的推移而扩展,人们应该能够根据键(及其值)创建特定的对象
正如您从伪代码示例中看到的那样,我可以为资源设置约束,但我需要一种方法来约束参数 属性 以仅允许与 Key
在 RoutingMap
export interface RoutingMessage {
resource: keyof RoutingMap,
params: RoutingMap[this["resource"]]
}
因为匹配 keyof RoutingMap
的键的数量有限,您可以将 RoutingMessage
写成 union 对象类型,其中联合的每个元素对应于一个特定的键,像这样:
type RoutingMessage = {
resource: "ticket";
params: {
id: number;
};
} | {
resource: "car";
params: {
model: string;
make: number;
};
}
您可以通过将 RoutingMap
编写为“分布式对象类型”(从 microsoft/TypeScript#47109) where we make a mapped type where each property with key K
in RoutingMap
is mapped to the desired object type for that key, and then we immediately index into 中借用的术语 keyof RoutingMap
以编程方式计算 RoutingMessage
,生成所需的工会。
type RoutingMessage = { [K in keyof RoutingMap]:
{ resource: K, params: RoutingMap[K] }
}[keyof RoutingMap];
根据上述定义,只要有新的 属性 添加到 RoutingMap
,RoutingMessage
就会根据需要获得新的联合成员。
让我们确保它的行为符合您的要求:
const msg: RoutingMessage = {
resource: "ticket",
params: { id: 10 }
}; // okay
const invalidMsg: RoutingMessage = {
resource: "something", // error!
//~~~~~~ <-- Type '"something"' is not assignable to type '"ticket" | "car"'
params: { id: 10 }
};
const invalidMsg2: RoutingMessage = {
resource: "car",
params: { model: "tesla", make: true } // error!
// --------------------> ~~~~
// Type 'boolean' is not assignable to type 'number'.
};
const invalidMsg3: RoutingMessage = {
resource: "car",
params: { id: 123 } // error!
// -----> ~~~~~~~
// Type '{ id: number; }' is not assignable to type '{ model: string; make: number; }'
};
看起来不错!
我有一个接口定义如下
export interface RoutingMap {
ticket: {
id: number
},
car: {
model: string,
make: number
}
}
我希望能够为对象创建一个接口,该对象具有 2 个属性 - 一个是 RoutingMap
中的键,另一个是 Key
中的任何类型RoutingMap
是。
在伪代码中我想象它看起来像这样
export interface RoutingMessage {
resource: keyof RoutingMap,
params: RoutingMap["resource"]
}
我的最终目标是能够构建这样的对象
const msg: RoutingMessage = {
resource: "ticket",
params: { id: 10 }
}
const invalidMsg: RoutingMessage = {
resource: "something", //TS error - "something" is not a key of routing map
params: { id: 10 }
}
const invalidMsg2: RoutingMessage = {
resource: "car"
params: { model: "tesla", make: true } //TS error - "make" is not a boolean
}
const invalidMsg3: RoutingMessage = {
resource: "car"
params: { id: 123 } //TS error - id is not assinable to {model: string, make: boolean}
}
RoutingMap
会随着时间的推移而扩展,人们应该能够根据键(及其值)创建特定的对象
正如您从伪代码示例中看到的那样,我可以为资源设置约束,但我需要一种方法来约束参数 属性 以仅允许与 Key
在 RoutingMap
export interface RoutingMessage {
resource: keyof RoutingMap,
params: RoutingMap[this["resource"]]
}
因为匹配 keyof RoutingMap
的键的数量有限,您可以将 RoutingMessage
写成 union 对象类型,其中联合的每个元素对应于一个特定的键,像这样:
type RoutingMessage = {
resource: "ticket";
params: {
id: number;
};
} | {
resource: "car";
params: {
model: string;
make: number;
};
}
您可以通过将 RoutingMap
编写为“分布式对象类型”(从 microsoft/TypeScript#47109) where we make a mapped type where each property with key K
in RoutingMap
is mapped to the desired object type for that key, and then we immediately index into 中借用的术语 keyof RoutingMap
以编程方式计算 RoutingMessage
,生成所需的工会。
type RoutingMessage = { [K in keyof RoutingMap]:
{ resource: K, params: RoutingMap[K] }
}[keyof RoutingMap];
根据上述定义,只要有新的 属性 添加到 RoutingMap
,RoutingMessage
就会根据需要获得新的联合成员。
让我们确保它的行为符合您的要求:
const msg: RoutingMessage = {
resource: "ticket",
params: { id: 10 }
}; // okay
const invalidMsg: RoutingMessage = {
resource: "something", // error!
//~~~~~~ <-- Type '"something"' is not assignable to type '"ticket" | "car"'
params: { id: 10 }
};
const invalidMsg2: RoutingMessage = {
resource: "car",
params: { model: "tesla", make: true } // error!
// --------------------> ~~~~
// Type 'boolean' is not assignable to type 'number'.
};
const invalidMsg3: RoutingMessage = {
resource: "car",
params: { id: 123 } // error!
// -----> ~~~~~~~
// Type '{ id: number; }' is not assignable to type '{ model: string; make: number; }'
};
看起来不错!