我正在尝试利用反应类型来实现(用于学习purpuse)一个视图框架。除了尝试将conditional type
与Omit
类型混合(以展示它需要包装@types/react
)时,一切都很好和花花公子:
import {DetailedHTMLFactory, ReactHTML} from 'react'
type Tags = keyof ReactHTML
type ReactPropsFrom<Tag extends Tags> =
ReactHTML[Tag] extends DetailedHTMLFactory<infer P, any> ? P : never
在这一点上,根据使用(对于锚点)HTMLElement
的反应定义,我确实拥有ReactPropsFrom<'a'>
的属性。剩下要做的是去除反应特定的属性。让我们来定义一些:
type ReactSpecificProps = |
'defaultChecked' |
'defaultValue' |
'suppressHydrationWarning' |
'suppressContentEditableWarning'
和Omit
类型
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
如果我做Omit<ReactPropsFrom<'a'>, ReactSpecificProps>
一切都很好,我在结果类型中确实有我想要的所有属性。
但如果我做一个更通用的方法,如下:
type Props<Tag extends Tags> = Omit<ReactPropsFrom<Tag>, ReactSpecificProps>
我最终得到了这个错误
// type ReactSpecificProps = "defaultChecked" |...
// Type '"defaultChecked"' is not assignable to type 'keyof ReactPropsFrom<Tag>'.
// Type '"defaultChecked"' is not assignable to type 'never'
我确实理解它,因为ReactPropsFrom
可能会返回never
(即使它永远不会是这种情况,因为通用传递总是扩展Tags
),并且在那种情况下类型检查器中断。但正如我理解为什么我无法想办法避免这个问题。
天真地,我跳过这样的东西:
type Props<Tag extends Tags> = Omit<ReactPropsFrom<Tag>!, ReactSpecificProps>
与bang !
运算符(因为我知道它永远不会是never
)但它不能用于类型定义(?)。任何线索?
在此先感谢Seb
您可以通过很多麻烦来说服编译器ReactPropsFrom<Tag>
确实包含ReactSpecificProps
,但我会建议反对它。 3.5中出现的Omit
类型不会将K
约束为keyof T
(PR和declination to add the constraint)。因此,解决方案是只删除K
上的约束,它将全部起作用。
为了完整起见,这就是令编程人员有信心的东西(至少我想出的是,可能有更短的方法):
type Props<Tag extends Tags> = ReactPropsFrom<Tag> extends infer U ?
[U] extends [Partial<Record<ReactSpecificProps, any>>] ? Omit<U, ReactSpecificProps> : never: never;