如何使用基于另一个参数的条件函数



我想要一个接受另一个函数的函数,该函数的签名会根据传递给该函数的另一个参数而更改。

例如:

function doSomething<AllowNull extends boolean>({ allowNull, onChange }: { allowNull: AllowNull, onChange: AllowNull extends true ? (input: number | null) => void : (input: number) => void }) {
if (allowNull) {
onChange(null);
} else {
onChange(1);
}
}

但是Typescript抱怨null不能传递给onChange,因为它没有缩小签名的范围。

我也尝试过函数重载:

function doSomething(props: { allowNull: true, onChange: (input: number | null) => void }): void
function doSomething(props: { allowNull: false, onChange: (input: number) => void }): void
function doSomething({ allowNull, onChange }: { allowNull: boolean,onChange: (input: number | null) => void }): void {
if (allowNull) {
onChange(null);
} else {
onChange(1);
}
}

但是Typescript抱怨其中一个重载签名与实现不兼容。

如何以类型安全的方式实现这种模式?

链接到TS游乐场,以便您可以看到错误。

您可以在参数中使用并集。这将允许Typescript(4.6及更新版本(基于allowNull:缩小onChange


function doSomething({ allowNull, onChange }:
| { allowNull: true, onChange: (input: number | null) => void }
| { allowNull: false, onChange: (input: number) => void }): void {
if (allowNull) {
onChange(null);
} else {
onChange(1);
}
}

游乐场链接

对于4.6之前的版本,你不能在参数中进行破坏,但你仍然可以缩小:Playground Link

最新更新