typescript 基于泛型扩展类型脚本的可选参数

0sgqnhkj  于 2023-02-10  发布在  TypeScript
关注(0)|答案(2)|浏览(155)

我将创建一个可以接收可选的第二个参数(params)的函数,ts应该根据第一个参数推断类型,例如
如果第一个参数的类型等于“ALERT”,则ts应该要求第二个参数作为具有title和onSend的对象
如果第一个参数的类型等于“LOGIN”,则第二个参数不存在,因此ts不应发送任何错误。
我得到了一种推断类型的方法,但是当DTO发送未定义的类型时,函数甚至不应该发送错误。

enum Dropups {
  LOGIN,
  ALERT,
}

interface AlertDTO {
  title: string;
  onSend: () => void;
}

type DTOSwitcher<T extends keyof typeof Dropups | undefined> = T extends "ALERT"
  ? AlertDTO
  : undefined;

interface DropupActions {
  openDropup<T extends keyof typeof Dropups>(
    type: T,
    options: DTOSwitcher<T>
  ): void;
}

const openDropup: DropupActions["openDropup"] = (type, options) => {
  return null;
};

openDropup("ALERT", {
  title: "Hey",
  onSend: () => null,
}); // TS infers correct option types

openDropup("LOGIN", undefined) // OK, but doesnt make sense send undefined here.
openDropup("LOGIN"); // NOT OK, but should be. 2 arguments were expected. Second option type should be equal to 'undefined'

尝试在接口上使用可选类型。但对于需要第二个参数的类型,TS未按预期显示任何类型错误。

interface DropupActions {
  openDropup<T extends keyof typeof Dropups>(
    type: T,
    options?: DTOSwitcher<T>
  ): void;
}
wswtfjt7

wswtfjt71#

我建议采取不同的做法:

// create function parameter first, as tuples :
type openParams = [type: "LOGIN" ] | [type : "ALERT", options: AlertDTO]

// use that tuple as parameters :
interface DropupActions {
  openDropup(...params:openParams): void;
}

const openDropup: DropupActions["openDropup"] = (...params : openParams) : void => {
  return ;
};

openDropup("ALERT", {title: "Hey",onSend: () => null}); 
openDropup("ALERT"); // not compile
openDropup("LOGIN", undefined) // not compile
openDropup("LOGIN");

希望这对你有用。

uemypmqf

uemypmqf2#

我通常用函数重载来解决这个问题,就像这样。
我简化了返回的类型,因为我不完全理解您试图实现什么,并且您的问题特别是输入参数。

enum Dropups { LOGIN, ALERT }

interface AlertDTO {
  title: string;
  onSend: () => void;
}

function openDropup(type: "ALERT", options: AlertDTO): void;
function openDropup(type: "LOGIN"): void;
function openDropup(type: keyof typeof Dropups, options?: AlertDTO): void {
  // Now do something here
}

openDropup("ALERT", { title: "Hey", onSend: () => null,}); // OK
openDropup("LOGIN", undefined) // Not accepted as it makes no sense
openDropup("LOGIN"); // Ok now

而且我通常使用联合类型而不是枚举,因为我认为它们更容易管理。

type Dropups = "ALERT" | "LOGIN";

这将消除keyof typeof Dropups部分
希望这个有用。

相关问题