版本
类型脚本4.2.4
输入4.3.0-dev.20210417
预期行为
对Box
组件所做的任何更改都具有快速验证和自动完成关联属性的功能。
实际行为
TypeScript验证和自动完成速度缓慢。
说明
我一直在研究当前的趋势,即创建一个通用的React元素,该元素将通过element
属性和相关属性并调用React.createElement
。类似的方法被一些著名的项目使用,如Material UI和Github Primer。我希望确保TypeScript将从给定的element
属性推断出正确的属性。我编写的代码确实可以工作,但是它似乎对性能有很大的影响。
相关
此问题可能与以下问题相关:第一个是第二个是第三个是第四个
示例
一个可重现的小示例可在以下网址找到:https://github.com/scottwillmoore/react-box。您也可以在CodeSandbox中进行试验。CodeSandbox版本有一些不同。
下面是TypeScript的主要内容:
import React from "react";
type ElementType = keyof JSX.IntrinsicElements;
type ElementProperties<T extends ElementType> = JSX.IntrinsicElements[T];
type WithElement<T extends ElementType> = {
element: T;
} & ElementProperties<T>;
type WithChildren = {
children?: React.ReactNode;
};
type BoxProperties<T extends ElementType> = WithElement<T> & WithChildren;
function Box<T extends ElementType>({ element, children, ...properties }: BoxProperties<T>) {
return React.createElement(element, properties, children);
}
export default function App() {
return (
<Box element="a" href="#">
Hello, world!
</Box>
);
}
8条答案
按热度按时间x0fgdtte1#
快速更新,我已将实现更改为:
这是基于Chakra UI implementation的,它似乎大大加快了验证和自动完成。如果你排除了
Join
,它也不起作用,我觉得这不应该有什么区别...即使简化为:
一旦
Omit
被移除,推论就不起作用了。有人知道为什么会发生这种情况吗?xqk2d5yq2#
检查次数:
TS 3.7 - 1.0秒
TS 3.8 - 1.1秒
TS 3.9 - 1.5秒
它看起来在之前和之后都很稳定。注意,对于这么多的代码来说,即使是3. 7也很慢。
pxy2qtax3#
#41821没有帮助。
cigdeys34#
哦,对不起,我应该提到它不是性能退化,而是一个需要改进的领域,因为这种模式在几个流行的React组件库中相当流行。我将研究#41821,它看起来确实很相似。另外,你知道为什么在我的第二个示例中省略
Omit
会导致类型推理不起作用吗?dm7nw8vv5#
不用担心,检查回归只是性能调查的正常部分。
只是为了设置期望值,
ElementType
是一个巨大的联合体,几乎总是会导致性能问题。我会看看这个特定代码中是否有什么可以改进的地方,但是,正如你在链接的bug中看到的,这已经得到了很多关注。我对这些类型不是很熟悉,所以你需要更具体地回答你关于emit的问题。我试着用你的第二个实现替换你建议的
BoxProps
,然后从<Box>
元素中删除href
属性,补全建议把它加回去。你是指别的吗?编辑:我忘了删除
Omit
.🤦 ♂️okxuctiv6#
下面是一个更简单的版本,但我仍然不知道为什么会出现错误:
x6492ojm7#
至少对于我的简化版本,我认为问题是编译器没有利用
T extends "symbol"
隐含T extends string
的事实,所以ComponentProps<T>
永远不会是never
(如果是,p2 = p1
将是一个错误)。这就解释了为什么
Omit<Type1, never>
与Type1
不一样。我还没有完全了解它为什么会影响示例中的智能感知,但我相信答案是相似的-编译器并不完全确定类型,因此它不提供成员。8cdiaqws8#
这真的很奇怪,谢谢你调查这个问题。我想我明白你的逻辑,如果
T extends "symbol"
,编译器不知道T extends string
是隐含的,因此p2: ComponentProps<T>
,其中T extends "symbol"
有条件地变成never
。我仍然不太明白Omit
是如何修复这个问题的,但我有一些空闲时间快速浏览了一下其他TypeScript问题,并发现了这个问题#36981,这导致我提出了这个拉取请求#42524,它可能相关,也可能不相关。