props 的类型被正确地推断为void,但它只有在我将undefined作为参数传递时才有效.

有没有可能不把任何东西作为论据传递?

const openModal = <T>(
  modal: (props:T) => void,
  props: {} extends Omit<T, "onClose"> ? void : Omit<T, "onClose">
) => {
  return;
};

const ModalOne = (props: {onClose: () => void}) => {
    return;
}

const ModalTwo = (props: {text: string, onClose: () => void}) => {
    return;
}

openModal(ModalOne) // not working (Expected 2 arguments, but got 1. An argument for 'props' was not provided.)

openModal(ModalOne, {}) // not working (Argument of type '{}' is not assignable to parameter of type 'void'.)

openModal(ModalOne, undefined) // working

openModal(ModalTwo, {text: 'test'}) // working

推荐答案

不幸的是,使用the void type来生成function parameter optional(如在microsoft/TypeScript#27522中实现的)并不完全受支持.它不像microsoft/TypeScript#29131中描述的那样,倾向于与generics一起工作.这被认为是TypeScrip中的一个错误,但它已经存在了很长一段时间,没有迹象表明它会很快或永远得到修复.出于这个原因,我建议您避免使用void(事实上,void在很多情况下都表现得很奇怪,所以您可能应该总是稍作停顿,以确保它确实是您想要使用的).

相反,您可以使用rest parameter of a tuple type实现"可能可选"的函数参数,其中元组类型取决于您要判断的任何条件.例如:

const openModal = <T,>(
    modal: (props: T) => void,
    ...[props]: {} extends Omit<T, "onClose"> ?
        [props?: Omit<T, "onClose">] :
        [props: Omit<T, "onClose">]
) => {
    return;
};

因此,从技术上讲,openModal是一个变量函数,其剩余参数...[props]是类型[props?: Omit<T, "onClose">](元素为optional的单元素元组)或类型[props: Omit<T, "onClose">](元素是必需的单元素元组).因为...[props]使用destructuring assignment,所以这会在函数内部给出一个props参数,它的类型是Omit<T, "onClose">还是Omit<T, "onClose"> | undefined,具体取决于类型T.

当你调用它时,如果空对象类型可以赋值给T,那么你可以用一个参数调用openModal().否则需要两个参数:

const ModalOne = (props: { onClose: () => void }) => { };
openModal(ModalOne); // okay
openModal(ModalOne, {});// okay
openModal(ModalOne, undefined); // okay

const ModalTwo = (props: { text: string, onClose: () => void }) => { };
openModal(ModalTwo); // error 
openModal(ModalTwo, {}); // error
openModal(ModalTwo, undefined); // error
openModal(ModalTwo, { text: 'test' }); // okay

const ModalThree = (props: { text?: string, onClose: () => void }) => { };
openModal(ModalThree); // okay
openModal(ModalThree, {}); // okay
openModal(ModalThree, undefined); // okay
openModal(ModalThree, { text: 'test' }); // okay

看起来像你想要的行为.

Playground link to code

Typescript相关问答推荐

React组件数组及其props 的类型定义

即使子网是公共的,AWS CDK EventBridge ECS任务也无法分配公共IP地址

如果在TypeScript中一个原始的类方法是递归的,如何使用类decorator 模式?

如何在第一次加载组件时加载ref数组

创建一个根据布尔参数返回类型的异步函数

React重定向参数

类型脚本返回的类型包含无意义的泛型类型名称

如何使所有可选字段在打印脚本中都是必填字段,但不能多或少?

类型脚本可以推断哪个类型作为参数传递到联合类型中吗?

React router 6(数据路由)使用数据重定向

如何从上传文件中删除预览文件图标?

在TypeScript中,如何通过一系列过滤器缩小类型?

VUE 3类型';字符串';不可分配给类型';参考<;字符串&>

类型判断数组或对象的isEmpty

内联类型断言的工作原理类似于TypeScrip中的断言函数?

在Vite中将SVG导入为ReactComponent-不明确的间接导出:ReactComponent

如何限定索引值必须与相应属性的id字段相同

Angular 16:无法覆盖;baseUrl;在tsconfig.app.json中

在Nestjs中,向模块提供抽象类无法正常工作

如何在没有空接口的情况下实现求和类型功能?