[英]Enforce single required property on Typescript interface, allow others
I am creating a generic WebSocket component.我正在创建一个通用的 WebSocket 组件。 I want to require the type
Message
to have a required property called type
.我想要求
Message
类型具有一个名为type
的必需属性。
export type Message = {
type: string;
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
};
The component is given a series of callback functions that are called when a Message
of the appropriate type
is called.该组件被赋予了一系列回调函数,当调用适当
type
的Message
时会调用这些回调函数。
export interface Listeners {
[type: string]: (msg: Message) => void;
}
Code snippet of WebSocket implementation: WebSocket 实现的代码片段:
...
ws.onmessage = (event: MessageEvent): void => {
console.log("[websocket] got raw message", event.data);
try {
const msg = JSON.parse(event.data);
if (listeners[msg.type]) {
console.log("[websocket] got message", msg);
listeners[msg.type](msg);
}
}
}
...
When using the WebSocket component, I'd like to define a custom type is an extension of the Message
type, and includes the type
property.在使用 WebSocket 组件时,我想定义一个自定义类型是
Message
类型的扩展,并包含type
属性。
interface GraphMessage extends Message {
id: string;
type: "initial" | "update";
chartType: "line" | string;
data: GraphPoint[];
}
I'm trying to use the component like so:我正在尝试像这样使用组件:
const handleUpdate = (msg: GraphMessage) => {}
const handleInitial = (msg: GraphMessage) => {}
const ws = await websocket("ws://localhost:9999/", {
initial: handleInitial,
update: handleUpdate
});
However, I'm received a Typescript error:但是,我收到了一个打字稿错误:
TS2322: Type '(msg: GraphMessage) => void' is not assignable to type '(msg: Message) => void'.
Types of parameters 'msg' and 'msg' are incompatible.
Type 'Message' is not assignable to type 'GraphMessage'.
How can I make Message
assignable to type GraphMessage
?如何使
Message
可分配到类型GraphMessage
?
Edit: I believe I've found a solution which is to make Message
a generic type.编辑:我相信我已经找到了使
Message
成为通用类型的解决方案。
type Message<T> = {
type: string
[key: string]: any
} & T
interface GraphMessage {
graphName: string
}
type Callback = (msg: Message<GraphMessage>) => void
const myBaseMessage = {
t...
TypeScript is right to point out that Type '(msg: GraphMessage) => void' is not assignable to type '(msg: Message) => void'
. TypeScript 正确地指出
Type '(msg: GraphMessage) => void' is not assignable to type '(msg: Message) => void'
。
If your handler depends on GraphMessage
but you provide just a Message
, this can result in runtime exceptions:如果您的处理程序依赖于
GraphMessage
但您只提供了一个Message
,这可能会导致运行时异常:
// Can, but doesn't have to include `id`
export type Message = {
type: string;
[key: string]: any;
};
interface GraphMessage extends Message {
id: string;
type: "initial" | "update";
}
const message: Message = {
type: 'foo',
}
const handler = (msg: GraphMessage): void => {
console.log(msg.type.toLocaleLowerCase());
}
If we do如果我们这样做
handler(message); // Compile-time error
TypeScript will prevent an exception from being thrown. TypeScript 将防止抛出异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.