译:这种模式会破坏 React 应用程序的 TS 性能

原文:https://www.totaltypescript.com/react-apps-ts-performance
作者:Matt Pocock
译者:ChatGPT 4 Turbo

编者注:只要记住一点,interface extends 通常比 & 快,详见 TypeScirpt Wiki 的性能建议

几年前,Sentry 在他们的 React 应用程序上遇到了大问题。他们不久前刚刚将其迁移到 TypeScript。并且这个应用是一个大型单体仓库的一部分。

但是 IDE 的性能很慢。你常常需要等待几秒钟,以后对 TypeScript 语言服务器进行更新。运行 tsc 也需要很长时间。

现在,对于一个大型 TypeScript 代码库来说,这并不罕见。但是 Sentry 团队有种预感,觉得有些不对劲。问题与代码库的大小不成比例。

结果表明,问题,如 Jonas 所概述的,归咎于单一模式。

如何拖垮你的 React 应用的 TS 性能

在 Sentry 的代码库的许多地方,他们都在扩展 React 中的 HTML 类型。例如,定义 ButtonProps 将如下所示:

import React from "react";
 
type ButtonProps =
  React.HTMLAttributes<HTMLButtonElement> & {
    extraProp: string;
  };
 
const Button = ({ extraProp, ...props }: ButtonProps) => {
  console.log(extraProp);
  return <button {...props} />;
};

这意味着你可以传入所有 <button> 元素可以接受的 props,再加上一个 extraProp

<Button
  extraProp="whatever"
  onClick={(e) => {
           // (parameter) e: React.MouseEvent<HTMLButtonElement, MouseEvent>
  }}
/>;

但事实证明,这种模式异常缓慢。因此 Jonas,遵循 TypeScript 性能 Wiki 的建议,将它们中的每一个都改为使用 interface

import React from "react";
 
interface ButtonProps
  extends React.HTMLAttributes<HTMLButtonElement> {
  extraProp: string;
}

突然间,事情变得更加迅速了。TypeScript 语言服务器更快了,tsc 运行也更快了。仅仅是一点语法的改变。为什么呢?

为什么会这样?

你可能听说过 interfacetype 稍微快那么一点。这其实并不完全正确。事实上,interface extends 稍微比 & 快一些。

在这篇文章的早期版本中,基于一些模糊的思考,我发表了一篇解释,感谢我以前的同事 Mateusz Burzyński,现在我明白了那是错误的。

问题比我意识到的要复杂 —— 查看这个 Thread了解他的批评和我们的调查。

希望,我能再次更新这篇文章,用一个明确的描述来解释为什么会这样 —— 但当涉及到 TypeScript 性能时,没有什么是简单的。

总而言之 —— interface extends 通常比 & 快,这个案例也证明了这一点。