Create React App 如何允许 Array.prototype.at() 而 TypeScript 不允许?
Posted
技术标签:
【中文标题】Create React App 如何允许 Array.prototype.at() 而 TypeScript 不允许?【英文标题】:How does Create React App allow for Array.prototype.at() while it's not allowed by TypeScript? 【发布时间】:2021-12-29 07:29:20 【问题描述】:在我们的 CRA 项目中,我们有这样的代码:
const patTable = tables['pat'].at(0);
Array.prototype.at()
功能是一个新功能,在旧版浏览器(例如 Chrome 89)中不可用。但由于某种原因,CRA 甚至没有发出警告或错误消息,并且很容易接受它。它还没有填充 .at()
函数,现在它正在破坏旧浏览器中的应用程序。
WebStorm 显示的推断类型为Table | undefined
(由于@types/node 16.x,但我不确定)。
还要注意 TypeScript 还不支持.at()
,例如:
function foo(values: string[])
const value = values.at(0);
引发错误:Property 'at' does not exist on type 'string[]'.(2339)
Sandbox
您是否有任何想法,TS 检查、linting 或构建都没有检测到问题怎么可能?
TS版本为:4.3.5
tsconfig.json
是:
"compilerOptions":
"target": "es6",
"lib": ["dom", "dom.iterable", "esnext"],
"sourceMap": true,
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"jsx": "react-jsx",
"baseUrl": "src",
"noFallthroughCasesInSwitch": true
,
"include": ["src", "types/global-fetch.d.ts"]
【问题讨论】:
"lib": ["dom", "dom.iterable", "esnext"],
注意esnext
不,它不影响它。在我们的项目中,唯一受esnext
影响的行是someString.replaceAll(...)
。 100%。
@Onkeltem - 虽然它现在不会,但它会,所以你需要考虑"esnext"
是否真的适合这个项目。
谢谢@T.J.Crowder,我明白了。是的,我宁愿附上一些特定的 polyfill。例如:仅限我的replaceAll()
。
【参考方案1】:
即使您正在处理面向浏览器的代码,它也可能是从 Node.js 类型中提取出来的。 Node.js 的类型包括RelativeIndexable
——来自@types/node/globals.d.ts
:
//#region ArrayLike.at()
interface RelativeIndexable<T>
/**
* Takes an integer value and returns the item at that index,
* allowing for positive and negative integers.
* Negative integers count back from the last item in the array.
*/
at(index: number): T | undefined;
interface String extends RelativeIndexable<string>
interface Array<T> extends RelativeIndexable<T>
interface Int8Array extends RelativeIndexable<number>
interface Uint8Array extends RelativeIndexable<number>
interface Uint8ClampedArray extends RelativeIndexable<number>
interface Int16Array extends RelativeIndexable<number>
interface Uint16Array extends RelativeIndexable<number>
interface Int32Array extends RelativeIndexable<number>
interface Uint32Array extends RelativeIndexable<number>
interface Float32Array extends RelativeIndexable<number>
interface Float64Array extends RelativeIndexable<number>
interface BigInt64Array extends RelativeIndexable<bigint>
interface BigUint64Array extends RelativeIndexable<bigint>
//#endregion ArrayLike.at() end
我在使用 Node 构建的项目中使用 Node.js 类型时遇到了这个问题,即使它们是为浏览器构建的。 (我主要是在setTimeout
的返回值上遇到它。)我刚刚检查了一个项目,果然,它很高兴使用at
(并将其解析为上述问题),即使我从未明确表示过在项目中安装了@types/node
。
我不使用 WebStorm,但在 VSCode 中,您可以通过将光标放在 at
上并按 F12 以“转到定义”来检查 at
的类型来自何处。大概 WebStorm 也有类似的东西。
我认为这是有用的信息,并且比评论更适合作为答案,但它确实提出了一个问题“那么我该如何防止这种情况发生?”我不得不承认我现在无法回答。我已将答案标记为 CW,希望有人可以更新以解决它。
【讨论】:
还是谢谢你!我确认我在node_modules/@types/node
下具有完全相同的 typedef - 即节点(v.16)。 IDE 的行为似乎相似 - WS 也从那里使用类型。但是我无法回答 CRA 的 webpack 如何“神奇地”使用这个.at()
。看起来有一个临时的 polyfill,它在类型检查时使用,然后在构建时搁置(因此进入构建的应用程序时不会受到影响)。
在构建过程中代码不会运行,对吧?这是客户端代码。所以没有临时的 polyfill 或任何东西,只有 @types/node
类型让 TypeScript 认为 at
会在运行时出现,而它不会(必然)存在。
唷,它是多么复杂。那些节点 16 类型通过依赖项意外出现。那么绝对值得禁用这种自动类型......采集。我希望我可以在tsconfig.json
中使用"exclude": ["node_modules/@types/node/globals.d.ts"]
来做到这一点,但是......不。这不是办法。毕竟为什么要在构建浏览器应用程序时包含 node 类型?以上是关于Create React App 如何允许 Array.prototype.at() 而 TypeScript 不允许?的主要内容,如果未能解决你的问题,请参考以下文章
sh 用于将工作证书链接到create-react-app的脚本。允许您使用create-react-app和有效的SSL证书。
为啥我收到此错误 - 错误:EPERM:不允许操作,找不到 mkdir 'C:\Users\Aniket' 命令:create-react-app
是否可以将装饰器与 create-react-app 一起使用?