我想要一个接受另一个函数的函数,该函数的签名会根据传递给该函数的另一个参数而更改。
例如:
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