簡體   English   中英

在 Typescript 接口上強制執行單個必需屬性,允許其他屬性

[英]Enforce single required property on Typescript interface, allow others

我正在創建一個通用的 WebSocket 組件。 我想要求Message類型具有一個名為type的必需屬性。

export type Message = {
  type: string;
  [key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
};

該組件被賦予了一系列回調函數,當調用適當typeMessage時會調用這些回調函數。

export interface Listeners {
  [type: string]: (msg: Message) => void;
}

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);
    }
  }
}
...

在使用 WebSocket 組件時,我想定義一個自定義類型是Message類型的擴展,並包含type屬性。

interface GraphMessage extends Message {
  id: string;
  type: "initial" | "update";
  chartType: "line" | string;
  data: GraphPoint[];
}

我正在嘗試像這樣使用組件:

const handleUpdate = (msg: GraphMessage) => {}
const handleInitial = (msg: GraphMessage) => {}

const ws = await websocket("ws://localhost:9999/", {
  initial: handleInitial,
  update: handleUpdate
});

但是,我收到了一個打字稿錯誤:

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'.

如何使Message可分配到類型GraphMessage

編輯:我相信我已經找到了使Message成為通用類型的解決方案。

type Message<T> = {
    type: string
    [key: string]: any
} & T

interface GraphMessage {
    graphName: string
}

type Callback = (msg: Message<GraphMessage>) => void

const myBaseMessage = {
    t...

游樂場鏈接

TypeScript 正確地指出Type '(msg: GraphMessage) => void' is not assignable to type '(msg: Message) => void'

如果您的處理程序依賴於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());
}

如果我們這樣做

handler(message); // Compile-time error

TypeScript 將防止拋出異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM