方法重载Typescript,从第一个参数类型推断第二个参数类型

lmyy7pcs  于 7个月前  发布在  TypeScript
关注(0)|答案(2)|浏览(106)

我试图在Typescript中实现方法oveloading。我想根据不同的参数对方法调用进行更严格的类型检查。例如,我想通过第一个参数的值推断第二个参数的类型,这是enum。我得到了一个错误:
“props”可能是“undefined”。
下面是一段代码(playground):

export default class ControlsContr {
  // constructor(public state: Signal<State> = signal(State.Idle)) {}

  dispatch(ev: Event.Reset): void;
  dispatch(ev: Event.Delete, props: { id: number }): void;
  dispatch(ev: Event, props?: { id?: number }): void {
    if (ev === Event.Delete) {
      const num: number = props.id;
    }
  }
}

export enum State {
  Idle = "Idle",
  Deleting = "Deleting",
  DeleteDone = "DeleteDone",
}

export enum Event {
  Delete = "Delete",
  Reset = "Reset",
}

function deleteItem(id: number) {
}

字符串
我想我的问题是,我试图实现的目标是否可能,如果可能的话,如何实现?

bt1cpqcv

bt1cpqcv1#

因为过载签名具有相关参数,您需要编写一个实现签名,以相同的方式将参数关联起来。您可以使用一种表示法,将参数表示为rest parametersdestructured元组,其类型是一个联合,其成员是表示重载签名中找到的相同配对的元组。这将允许编译器使用现有的判别条件。这里有一个例子来演示:
TSPlayground

class ControlsContr {
  dispatch(ev: Event.Reset): void;
  dispatch(ev: Event.Delete, props: { id: number }): void;
  dispatch(
    ...[ev, props]: [ev: Event.Reset, undefined?] | [
      ev: Event.Delete,
      props: { id: number },
    ]
  ) {
    if (ev === Event.Delete) {
      ev
    //^? (parameter) ev: Event.Delete
      props
    //^? (parameter) props: { id: number }

      const num = props.id; // ok
          //^? const num: number
    } else {
      ev
    //^? (parameter) ev: Event.Reset
      props
    //^? (parameter) props: undefined
    }
  }
}

字符串

k7fdbhmy

k7fdbhmy2#

根据Typescript的文档:
除了一般的类型string和number,我们还可以在类型位置引用特定的字符串和数字. [...]通过将文字组合成联合,你可以表达一个更有用的概念-例如,函数只接受一组已知值. [...]还有一种文字类型:布尔文字。
因此,你不能使用枚举。但是,你可以使用字符串:

export default class ControlsContr {
  dispatch(ev: "Reset"): void;
  dispatch(ev: "Delete", props: { id: number }): void;
  dispatch(ev: Event, props?: { id?: number }): void {}
}

export type Event = "Delete" | "Reset"

const controls = new ControlsContr()
controls.dispatch("Reset")
controls.dispatch("Delete", {id: 1})
// controls.dispatch("Reset", {id: 1}) fails
// controls.dispatch("Delete") fails

字符串
或通过歧视性工会:

export default class ControlsContr {
  dispatch(ev: Event): void {
    if (ev.action == "Delete") {
      console.log(ev.id)
    }
  }
}

type ResetEvent = {action: "Reset"};
type DeleteEvent = {action: "Delete", id: number};
type Event = ResetEvent | DeleteEvent

const controls = new ControlsContr()
controls.dispatch({action: "Reset"})
controls.dispatch({action: "Delete", id: 1})

相关问题