type ComponentType = (...args: any) => any;
type PlatformNotificationProps<TIcon extends ComponentType = ComponentType> = {
component: TIcon;
arg: Parameters<TIcon>[0];
};
const PlatformNotification = (props: PlatformNotificationProps) => {};
const Icon = (name: string) => '';
const result = PlatformNotification({
component: Icon,
arg: 100,
});
在这种情况下or 'arg'是不正确的,应该是一个字符串,或组件是不正确的,应该接受数字而不是字符串。我期望在控制台看到错误,但一切都很好。
如何编写这种情况下的类型?
您已经将PlatformNotification
定义为非泛型函数,不要指望它检查类型
const PlatformNotification = (props: PlatformNotificationProps) => {};
// ^?
// const PlatformNotification: (props: PlatformNotificationProps</*default*/ComponentType>) => void
const result = PlatformNotification({
component: Icon,
// ^?
// (property) component: ComponentType
arg: 100,
// ^?
// (property) arg: any
});
让它通用就行了
const PlatformNotification = <TIcon extends ComponentType>(props: PlatformNotificationProps<TIcon>) => {};
当使用泛型时,链上的所有类型都需要传递泛型参数。
由于您在PlatformNotificationProps
中默认参数,然后使用该类型而不配置它,因此TS将不知道将函数中的参数与泛型
的参数关联起来。有一种方法可以让链中的所有元素都是可配置的
type Fn<Args extends any[] = any[]> = (...args: Args) => any;
type PlatformNotificationProps<Args extends any[], TIcon extends Fn<Args>> = {
component: TIcon;
arg: Parameters<TIcon>[0];
};
const PlatformNotification = <Args extends any[] = any[], Comp extends Fn<Args> = Fn<Args> >(props: PlatformNotificationProps<Args, Comp>) => {};
const Icon = (name: string) => '';
const result = PlatformNotification({
component: Icon,
arg: 100,
});
主要问题是您正在为PlatformNotificationProps
分配默认泛型:
type PlatformNotificationProps<TIcon extends ComponentType = ComponentType> = {
...
当您调用该类型而没有适当的泛型类型时,typescript只能推断它是ComponentType
,这就是为什么arg
可以接受数字,因为它实际上是any
:
const result = PlatformNotification({
component: Icon,
arg: 100,
// ^? (property) arg: any
});
component
也一样:
const result = PlatformNotification({
component: () => null, // no errors
arg: 100,
});
为了解决这个问题,使用类型:
调用PlatformNotificationProps
const PlatformNotification = (props: PlatformNotificationProps<typeof Icon>) => {};
现在:
const result = PlatformNotification({
component: Icon,
arg: 100, // error: type `number` is not assignable to `string`
});