TypeScript 3.9 正式发布!平均编译时长从 26 秒缩短至 10 秒

作者 | 微软官方博客

译者 | 核子可乐

策划 | 小智

稿源 | 前端之巅

今天,微软在其官方博客宣布:TypeScript 3.9 版本已经正式发布,详情见下文。

有些朋友可能对 TypeScript 还不太熟悉,这是一种以 JavaScript 为基础开发的语言,新增 type 声明与注释等多种语法。TypeScript 编译器能够使用这些语法对代码进行 type 检查,而后输出能够适配多种不同运行时、且清晰可读的 JavaScript 代码。

由于 TypeScript 具有丰富的跨编辑器功能,因此其中的静态 type 检查能够在代码运行甚至文件保存之前快速指示代码中存在的错误。除了错误检查之外,TypeScript 还允许用户在自己熟悉的编辑器中为 TypeScript 以及 JavaScript 代码提供补全、快速修复以及重构等功能。事实上,如果你曾经使用过 Visual Studio 或者 Visual Studio Code,那么以往的 JavaScript 代码编写体验中可能就已经有 TypeScript 的贡献了。如果希望了解更多详细信息,请 访问我们的网站。

而如果你已经在项目当中使用过 TypeScript,那么直接通过以下 npm 命令或者通过 NuGet 都能快速获取我们发布的本次新版本:

npm install typescript

当然,你还可以通过以下方式获取编辑器支持:

下载 Visual Studio 2019/2017 对应版本;

https://marketplace.visualstudio.com/items?itemName=TypeScriptTeam.TypeScript-39

安装 Visual Studio Code Insiders 版本;

http://code.visualstudio.com/insiders

或者通过链接使用 TypeScript 新版本;

https://code.visualstudio.com/docs/typescript/typescript-compiling\l_using-newer-typescript-versions

配合 Sublime Text 3 使用 PackageControl。

https://packagecontrol.io/packages/TypeScript

在此次新版本中,我们的团队高度关注性能表现、细节处理与稳定性。我们一直努力提高编译器速度与编辑体验,摆脱卡顿与繁琐的细节,同时减少 bug 与系统崩溃问题。当然,我们也从外部社区收到了很多有价值的功能与修复贡献。

Inference 与 Promise.all 迎来改进

TypeScript 的最近几个版本(3.7 及之后)已经对 Promise.all 及 Promise.race 等函数的声明做出更新。遗憾的是,更新带来了新的问题,这一点在混合 null 或 undefined 值时体现得尤其明显。

interface Lion {roar(): void}interface Seal {singKissFromARose(): void}async function visitZoo(lionExhibit: Promise<Lion>, sealExhibit: Promise<Seal | undefined>) {let [lion, seal] = await Promise.all([lionExhibit, sealExhibit]);lion.roar(); // uh oh// ~~~~// Object is possibly 'undefined'.}

这种情况非常奇怪!事实上,sealExhibit 当中包含的 undefined,相当于是把 undefined 错误引入了 lion type 当中。

感谢 Jack Bates 提交的贡献,现在这个问题已经在 TypeScript 3.9 版本中得到修复。以上错误不复存在,如果大家仍在较早版本的 TypeScript 面临 Promise 的困扰,我们建议您尽快升级至 3.9 版本!

关于 awaited  type 的变化

如果大家一直在关注我们的问题跟踪器与设计研讨记录,可能已经注意到我们正在开发一种名为 awaited 的全新 type 操作符。该操作符的作用是准确对 JavaScript 中的 Promise 展开方式进行建模。

我们最初预计在 TypeScript 3.9 版本中发布 awaited,但在使用现有代码库运行早期 TypeScript build 时,我们意识到这项功能还需要进一步打磨才能正式交付。因此,我们决定将该功能从主分支中剥离出来,直到其做好服务用户的一切准备。我们将对这项功能进行更多试验,因此在 3.9 版本中 awaited 将暂时制度。

速度改进

TypeScript 3.9 将带来一系列新的速度改进机制。在发现 Material-ui 与 Styled-Components 等组件会带来极差的编辑 / 编译速度后,我们的团队一直努力进行性能优化。我们在这方面进行了深入研究,并提交多项 pull 请求以优化涉及大型联合、交集点、条件 type 以及映射 type 的性能问题。

  • https://github.com/microsoft/TypeScript/pull/36576

  • https://github.com/microsoft/TypeScript/pull/36590

  • https://github.com/microsoft/TypeScript/pull/36607

  • https://github.com/microsoft/TypeScript/pull/36622

  • https://github.com/microsoft/TypeScript/pull/36754

  • https://github.com/microsoft/TypeScript/pull/36696

在部分代码库上,相关 pull 请求的编译时间平均减少了 5% 至 10%。总体而言,我们已经将 material-ui-styles 项目的编译时间缩短约 25%。此外,我们还收到来自微软团队的反馈意见,他们表示 TypeScript 3.9 的平均编译时长由 26 秒缩短至 10 秒左右。

我们还对编辑器方案中的文件重命名功能做出几项调整。根据 Visual Studio Code 团队提供的建议,我们发现在执行文件重命名时,单是查明哪些导入语句需要更新就要耗去 5 到 10 秒时间。TypeScript 3.9 调整了内部编译器与语言服务缓存文件的查找方式,顺利解决了这个问题。

虽然仍有改善空间,但我们希望目前的成果能够为广大用户带来更好的使用体验!

// @ts-expect-error 注释

想象一下,如果我们正使用 TypeScript 编写一个库,并将名为 doSTuff 的函数作为公共 API 的一部分进行导出。该函数的 type 声明需要两个 strings,以便其他 TypeScript 用户正常获取 type-checking 错误。但与此同时,它还需要执行运行时检查(可能仅在开发 build 中)以向 JavaScript 用户提示错误信息。

function doStuff(abc: string, xyz: string) {assert(typeof abc === "string");assert(typeof xyz === "string");// do some stuff}

因此一旦发生操作失误,TypeScript 用户面对的将是一条标红的乱码信息外加一条错误信息。而 JavaScript 用户则面对一条断言错误。我们希望通过单元测试检查实际情况与预期是否相符。

expect(() => {doStuff(123, 456);}).toThrow();

遗憾的是,我们的测试是由 TypeScript 编写而成,而 TypeScript 只能提示一条错误信息!

doStuff(123, 456);//          ~~~// error: Type 'number' is not assignable to type 'string'.

为此,TypeScript 3.9 带来了新功能:// @ts-expect-error 注释。在一行代码以 // @ts-expect-error 注释作为前缀时,TypeScript 会禁止报告该错误。而如果没有发生错误,TypeScript 则报告不需要 // @ts-expect-error。

在以下简单示例代码中,一切正常运行:

// @ts-expect-errorconsole.log(47 * "octopus");

但下列代码:

// @ts-expect-errorconsole.log(1 + 1);

会导致错误:

Unused '@ts-expect-error' directive.

我们要特别感谢此项功能的贡献者 Josh Goldberg。关于更多详细信息,请参阅 ts-expect-error pull 请求:

https://github.com/microsoft/TypeScript/pull/36014

ts-ignore 还是 ts-expect-error?

在某种程度上讲,// @ts-expect-error 可以作为抑制注释使用,其效果类似于 // @ts-ignore。但二者的区别在于,如果下一行代码没有错误,则 // @ts-ignore 不会发挥任何作用。

大家可能打算把现有 // @ts-ignore 注释变更为 // @ts-expect-error,而且好奇哪种方法更适合用于后续代码编写。虽然具体选择取决于您和您的团队,但这里我们还是整理出了一些相对普适的选择思路。

如果符合以下条件,请选择 ts-expect-error :

  • 您正在编写测试代码,且希望 type 系统在单一操作上显示错误。

  • 您希望尽快获得修复方法,只要能解决问题就行。

  • 您的项目规模合理,团队工作态度积极主动,希望在受影响代码恢复正常之后马上删除抑制注释。

如果符合以下条件,请选择 ts-ignore :

  • 您的项目规模很大大,而且在缺少明确归属的代码中出现了新错误。

  • 您正在两种不同 TypeScript 版本之间升级,某行代码只在其中一个版本上出现了错误。

  • 您根本没有时间认真考虑这两个选项中哪个更好。

在条件表达式中检查未调用函数

在 TypeScript 3.7 版本中,我们引入了未调用函数检查(uncalled function checks)以提示那些您忘记调用的函数。

function hasImportantPermissions(): boolean {// ...}// Oops!if (hasImportantPermissions) {// ~~~~~~~~~~~~~~~~~~~~~~~
// This condition will always return true since the function is always defined.
// Did you mean to call it instead?deleteAllTheImportantFiles();}

然而,这种错误只适用于 if 语句。感谢 Alexander Tarasyuk 的贡献,现在此项功能已经能够正常支持三种条件(即 cond ? trueExpr : falseExpr 语法)。

declare function listFilesOfDirectory(dirPath: string): string[];
declare function isDirectory(): boolean;
function getAllFiles(startFileName: string) {const result: string[] = [];traverse(startFileName);return result;
    function traverse(currentPath: string) {return isDirectory ?// ~~~~~~~~~~~// This condition will always return true// since the function is always defined.// Did you mean to call it instead?listFilesOfDirectory(currentPath).forEach(traverse) :result.push(currentPath);}}

Alexander 还进一步提交了快速修复方案,旨在改善未调用函数检查功能的使用体验!

编辑器改进

TypeScript 编译器不只增强了大部分主流编辑器中的 TypeScript 编辑体验,同时也增强了 Visual Studio 系列编辑器中的 JavaScript 开发体验。根据您所使用的具体编辑器,新的 TypeScript/JavaScript 功能也会有所不同。以下为几项共通性改进:

  • Visual Studio Code 现在允许您选择不同的 TypeScript 版本。此外,JavaScript/TypeScript Nightly Extension 也将始终保持最新(通常相当稳定)。

  • Visual Studio 2017/2019 迎来最新版本的 SDK 安装器与 MSBuild 安装程序。

  • Sublime Text 3 支持用户选择不同 TypeScript 版本。

JavaScript 中的 CommonJS 自动补全

新版本的另一项重大改进,是使用 CommonJS 模块自动导入 JavaScript 文件。

在旧版本中,TypeScript 强制要求用户无论使用什么文件,都必须以 ECMAScript 的形式导入,例如:

import * as fs from "fs";

但在编写 JavaScript 文件时,很多用户并不打算使用 ECMScript 样式模块。不少朋友仍在使用 CommonJS 样式的 require(...) 导入,例如:

const fs = require("fs");

TypeScript 现在能够自动检测您所使用的导入类型,保证文件样式简洁而统一。

关于更多详细信息,请参阅相应 pull 请求:

https://github.com/microsoft/TypeScript/pull/37027

代码操作保留换行符

TypeScript 的重构与快速修复往往无法正确保留换行符。先来看以下简单代码示例:

const maxValue = 100;/*start*/for (let i = 0; i <= maxValue; i++) {// First get the squared value.let square = i ** 2;// Now print the squared value.console.log(square);}/*end*/

如果我们在编辑器中从 /*start*/ 到 /*end*/ 的高亮显示区域内提取一条新函数,则最终得出的代码将如下所示:

const maxValue = 100;printSquares();function printSquares() {for (let i = 0; i <= maxValue; i++) {// First get the squared value.let square = i ** 2;// Now print the squared value.console.log(square);}}

这就不对了——原本 for 循环中的每个语句间都有一个空白行,但重构之后空白行消失了!好消息是,TypeScript 在保持编写内容准确性方面做出不少改进。

const maxValue = 100;printSquares();function printSquares() {for (let i = 0; i <= maxValue; i++) {// First get the squared value.let square = i ** 2;// Now print the squared value.console.log(square);}}

关于更多详细信息,请参阅相应 pull 请求:

https://github.com/microsoft/TypeScript/pull/36688

快速修复缺失的返回表达式

在某些情况下,大家很可能会忘记返回函数中最后一条语句的值。这种情况在向箭头函数添加大括号时体现得尤其明显。

// beforelet f1 = () => 42// oops - not the same!let f2 = () => { 42 }

感谢社区成员 Wenlu Wang 的贡献,TypeScript 现在获得了快速修复功能,可添加缺失的 return 语句、删除大括号或者为对象字面量等箭头函数实体添加括号。

支持 “Solution Style” tsconfig.json 文件

编辑器需要确定当前文件属于哪个配置文件,以及当前“项目”中还包含哪些其他文件,从而选择适当的选项。在默认情况下,由 TypeScript 语言服务器支持的编辑器会在各个父目录中查找 tsconfig.json 以实现这一目的。

但问题在于,某些简单 tsconfig.json 会直接引用其他 tsconfig.json 文件。

// tsconfig.json{"files": [],"references": [{ "path": "./tsconfig.shared.json" },{ "path": "./tsconfig.frontend.json" },{ "path": "./tsconfig.backend.json" },]}

换句话说,这个文件的作用只是管理其他项目文件;在某些环境中,我们将这类文件称为“solution”。很明显,服务器无法正确提取这些 tsconfig.*.json 文件,但我们的目标正是让语言服务器意识到当前.ts 文件可能归属于 tsconfig.json 根目录所提及的其他项目。

TypeScript 3.9 解决了这个支持问题。关于更多详细信息,请参阅 相应的 pull 请求。

重大变化

解析可选链与非 null 断言中的差异

TypeScript 最近实现了对可选链操作符的支持,但根据用户反馈,非 null 断言操作符(!)的可选链(?.)行为不符合直觉。

具体来讲,在以往的版本中,代码:

foo?.bar!.baz

被解释为等效于以下 JavaScript 代码:

(foo?.bar).baz

在以上代码中,括号会阻止可选链的“短路”行为;因此如果未定义 foo 为 undefined,则访问 baz 会引发运行时错误。

发现这一问题的 Babel 团队以及向我们提交反馈的大部分其他用户,都认为这样的行为属于设计失误。我们完全认同大家的看法!根据群众和我们自己的内部意见,由于操作目的是从 bar type 中删除 null 与 undefined,因此!操作符应该直接“消失”。

换句话说,大多数人认为以上原始代码片段应该被解释为在:

foo?.bar.baz

中,当 foo 为 undefined 时,计算结果为 undefined。

这是一项重大变化,但我们认为大部分代码在编写时都是为了考虑新的解释场景。如果您希望继续使用旧有行为,则可在!操作符左侧添加括号,如下所示:

(foo?.bar)!.baz

} 与 > 现在为无效的 JSX 文本字符

JSX 规范禁止在文本位置中使用}与>字符,TypeScript 与 Babel 也遵循相同的规则。要在新版本中插入这些字符,您需要使用 HTML 转义代码 (例如 <div>2 &gt; 1</div> ) 或者插入一个带有字符串字面值的表达式 (例如 <div>2 {">"} 1</div> )。

幸运的是,由于 Brad Zacher 提交的 pull 请求,现在直接使用这两个符号会弹出以下错误提示:

Unexpected token. Did you mean `{'>'}` or `&gt;`?Unexpected token. Did you mean `{'}'}` or `&rbrace;`?

例如:

let directions = <div>Navigate to: Menu Bar > Tools > Options</div>// ~ ~// Unexpected token. Did you mean `{'>'}` or `&gt;`?

这条错误消息中还附带便捷的快速修复功能,感谢 Alexander Tarasyuk 的贡献,您的努力让批量处理错误修复变得非常轻松。

更严格地检查交集与可选属性

一般来说,如果 A 和 B 中的任何一个可被赋值给 C,那么像 A 与 B 这样的交集 type 就可以被赋值给 C;但有时候,可选属性会引发问题。例如:

interface A {a: number; // notice this is 'number'}interface B {b: string;}interface C {a?: boolean; // notice this is 'boolean'b: string;}declare let x: A & B;
declare let y: C;y = x;

在之前的 TypeScript 版本中,上述代码能够正常运行,因为 A 与 C 完全不兼容,而 B 与 C 兼容。

在 TypeScript 3.9 中,只要交集中的每个 type 都是一个具体的对象 type,则 type 系统将同时考虑所有属性。因此,TypeScript 会意识到 A&B 中的 A 属性与 C 不兼容:

Type 'A & B' is not assignable to type 'C'.Types of property 'a' are incompatible.Type 'number' is not assignable to type 'boolean | undefined'.

若需了解更多详细信息,请参阅相应 pull 请求:

https://github.com/microsoft/TypeScript/pull/37195

通过属性判断减少交集

在某些情况下,我们的 type 可能会描述并不存在的值,例如:

declare function smushObjects<T, U>(x: T, y: U): T & U;interface Circle {kind: "circle";radius: number;}interface Square {kind: "square";sideLength: number;}declare let x: Circle;
declare let y: Square;
let z = smushObjects(x, y);console.log(z.kind);

这段代码有点奇怪,因为我们实际上没有办法为 Circle 与 Square 创建出交集——二者拥有两个互不兼容的 kind 字段。在之前的 TypeScript 版本中,这段代码可以正常运行,只是 kind 本身由于 "circle" & "square" 描述的值集不可能存在而被解释为 never 。

在 TypeScript 3.9 当中,type 系统变得更为严格——它会意识到 Circle 与 Square 因为 kind 属性的不同而不可能存在交集。因此不同于旧版本将 z.kind type 折叠为 never,新版本会将 z type 本身(Circle & Square)折叠为 never。这意味着以上代码现在将提示以下错误:

Property 'kind' does not exist on type 'never'.

通过观察,我们发现大多数中断都由 type 声明中的瑕疵引发。若需了解更多详细信息,请参阅原始 pull 请求:

https://github.com/microsoft/TypeScript/pull/36696

Getters/Setters 不再属于可枚举属性

在 TypeScript 旧版本中,类中的 get 与 set 访问器会以可枚举形式发出;但这明显不符合 ECMAScript 规范。该规范要求将二者设定为不可枚举属性。因此,针对 ES5 与 ES2015 的 TypeScript 代码可能在实际执行中引发不同的行为。

感谢 GitHub 用户 pathurs 的贡献,TypeScript 3.9 已经在这方面向 ECMAScript 的要求看齐。

扩展 any 的 Type 参数不再作为 any 执行

在 TypeScript 的旧版本中,受 any 约束的 type 参数可被视为 any。

function foo<T extends any>(arg: T) {arg.spfjgerijghoied; // no error!}

这是一项明显的疏忽,因此 TypeScript 3.9 采用了更保守的方法,将针对这些有问题的操作发出错误提示。

function foo<T extends any>(arg: T) {arg.spfjgerijghoied;// ~~~~~~~~~~~~~~~// Property 'spfjgerijghoied' does not exist on type 'T'.}

始终保留 export *

在此前的 TypeScript 版本当中,如果 foo 没有导出任何值,则 export * from "foo"这类声明会在 JavaScript 输出结果中被直接删除。但这种处理方法并不完善,因为它是 type 定向的且无法被 Babel 模拟。TypeScript 3.9 将始终保留 export * 声明。在实践中,这项调整应该不会对代码造成太多实际影响,但捆绑程序对代码进行摇树时难度可能会有所提升。

若需了解更多版本变化,请参阅原始 pull 请求:

https://github.com/microsoft/TypeScript/pull/37124

导出当前用户 Getters 以实现活动绑定

当我们在 ES5 及以上版本中以 CommonJS 等模块系统为目标时,TypeScript 会使用 get 访问器以模拟活动绑定,以便在任意导出模块中都可体现对单一模块内变量的更改。此次变更的目标,在于进一步改善 TypeScript 输出代码与 ECMAScript 模块的兼容度。

关于更多详细信息,请参阅 这项变更的 pull 请求:

https://github.com/microsoft/TypeScript/pull/359670

导出结果的提升与初始赋值

配合 ES5 及更高版本中的 CommonJS 等目标模块系统,TypeScript 现在能够将导出的声明提升至文件顶部。这一改变意味着 TypeScript 的导出结果与 ECMAScript 模块将更加兼容。代码示例如下:

export * from "mod";export const nameFromMod = 0;

此前的输出结果为:

__exportStar(exports, require("mod"));exports.nameFromMod = 0;

但由于导出结果现在使用 get- 访问器,__exportStar 的存在使得赋值操作因该访问器无法被赋值简单覆盖而失败。在 TypeSCript 3.9 中,您需要使用以下命令:

exports.nameFromMod = void 0;__exportStar(exports, require("mod"));exports.nameFromMod = 0;

若需了解详细信息,请参阅原始 pull 请求:

https://github.com/microsoft/TypeScript/pull/37093

下一阶段目标

我们希望 TypeScript 3.9 能进一步提升您的日常开发体验并加快开发速度。关于后续版本,欢迎大家关注我们的 4.0 迭代计划与功能发展路线图。

4.0迭代计划:https://github.com/microsoft/TypeScript/issues/38510

功能发展路线图:https://github.com/Microsoft/TypeScript/wiki/Roadmap

延伸阅读

https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/284901.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(二)Harbor WEB的使用

接上一篇《安装Harbor》&#xff0c;安装好之后&#xff0c;接下来我们就进行Harbor web界面的操作吧&#xff01; 转载请标明出处&#xff1a;http://www.cnblogs.com/huangjc/p/6270405.html 浏览器登陆Harbor&#xff08;默认用户密码&#xff1a;admin/Harbor12345&#x…

iVX低代码平台系列制作简单的登录界面

一、前言 iVX是啥&#xff0c;不理解的小伙伴可以猛戳这里 ----------------------点我 二、iVX平台和现有编程语言的对比 三、iVX平台和现有编程语言的对比 1、快速学习&#xff08;周期短&#xff09; iVX逻辑上相对是比较简单的 所以初学者的话只需要从逻辑和具体功…

Process.Start 为什么会引发“系统找不到指定的文件”异常

前言偶然发现&#xff0c;如果想用如下代码在 .NET 6 中打开指定 URL&#xff1a;Process.Start("https://baidu.com");会引发异常&#xff1a;而同样的代码在 .NET Framework 中是可以正常执行的。难道&#xff0c;.NET 6 下的实现逻辑不一样&#xff1f;深入探究通…

JVM 类型的生命周期学习

Java虚拟机通过装载、连接和初始化一个JAVA类型&#xff0c;使该类型可以被正在运行的JAVA程序所使用&#xff0c;其中&#xff0c;装载就是把二进制形式的JAVA类型读入JAVA虚拟机中&#xff1b;而连接就是把这种读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时状态中去…

js对象数组中的某属性值 拼接成字符串

var arr[{id: "600", pId: null, name: "图形的变化"},{id: "630", pId: "600", name: "投影与视图"},{id: "631", pId: "630", name: "投影"},{id: "632", pId: "630",…

开店星简直就是国内优秀的开源商城系统天花板

一、场景 1、大学生毕业设计做商城系统背景 好家伙、又到开学季节了&#xff0c;师妹让我帮忙给指导大四的项目&#xff0c;作为毕业设计和为后面找工作积累项目经验&#xff0c;要搞一个买卖二手闲置品的商城小程序和PC端商城、希望能够快速学习、接入、修改部分功能&#xff…

【CASS精品教程】CASS9.1土方量的计算方法汇总

CASS9.1中,计算土方量的方法有:DTM法土方计算、断面法进行土方量计算、方格网法土方计算、等高线法土方计算、区域土方量平衡等。本文以案例的形式,详细讲解土方量的计算过程。 文章目录 一、DTM法土方计算二、断面法进行土方量计算三、方格网法土方计算四、等高线法土方计算…

VS2019 禁止Web项目停止调试后自动关闭浏览器(在浏览器窗口关闭时停止调试程序,在调试停止时关闭浏览器)

很多文章都说要修改以下两处与“编辑并继续”有关的选项&#xff1a; “编辑并继续”是一种省时的功能&#xff0c;使你能够在程序处于中断模式时更改源代码。 通过选择执行命令&#xff08;如 "继续" 或 "单步执行"&#xff09;继续执行程序时&#xff0c…

【ArcGIS风暴】ArcGIS中等高线高程标注/注记(打断/消隐)方法案例汇总

本文以案例的形式,图文并茂详细讲解在ArcGIS 10.6中,等高线高程标注、注记的方法。 文章目录 一、属性标注二、Maplex工具标注1. 使用Maplex标注引擎2. 标注转换为注记3. 要素轮廓线掩膜4. 使用掩膜选项进行绘制参考阅读: 【CASS精品教程】CASS9.1等高线的绘制完整案例教程 …

Blazor University (35)表单 —— 编写自定义验证

原文链接&#xff1a;https://blazor-university.com/forms/writing-custom-validation/编写自定义验证源代码[1]请注意&#xff0c;与有关 EditContext、FieldIdentifiers 和 FieldState[2] 的部分一样&#xff0c;这是一个高级主题。如前所述&#xff0c;FieldState 类保存表…

HTML 元素内部添加预加载

CSS&#xff1a; /*元素内部加载loading*/.innerLoading {height: 100%;width: 100%;display: flex;justify-content: center;align-items: center;}.innerLoading * {text-align: center;color: #737782cc;fill: #73777A;font-size: 1em !important;font-family: SimSun,SimHe…

Windows下怎样安装Tomcat

Tomcat 是开源的WEB应用容器&#xff0c;所以受到各位程序员和公司的亲赖。在这里给大家介绍一下如何在Windows环境下安装Tomcat绿色版本&#xff0c;希望能够对大家有帮助。 1.首先去Tomcat官网下载Tomcat软件&#xff0c;在百度中搜索Tomcat,进入英文网址http://tomcat.apach…

智能识别云服务端平台之神【合合信息TextIn】

一、前言 众所周知&#xff0c;随着互联网和人工智能的发展&#xff0c;我们非常多的场景需要用到智能“识别”功能&#xff0c;比如人脸识别、通用文字识别、表格识别、办公文档识别、身份证、名片、营业执照等国内外卡证文字识别等等&#xff0c;同时识别与理解面临的全球性技…

【ArcGIS微课1000例】0015:ArcGIS如何创建/自定义快捷键?

为了提高工作效率,强大的ArcGIS提供了很多快捷键,如访问 ArcMap 菜单命令、窗口操纵、刷新或暂停地图绘制、通过拖放进行移动或复制等等。本文在ArcGIS已有快捷键的基础之上,为了提高工作效率,讲解如何定制个性化的快捷键。 参考阅读:【ArcGIS风暴】ArcGIS快捷键大全 文章…

Bresenham 算法

1965 年&#xff0c;Bresenham 为数字绘图仪开发了一种绘制直线的算法&#xff0c;该算法同样使用于光栅扫描显示器&#xff0c;被称为 Bresenham 算法。 原理 算法的目标是选择表示直线的最佳光栅位置。Bresenhan 算法在主位移方向上每次递增一个单位。另一个方向的增量为 0…

ML.NET 更新

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;5分钟)ML.NET是一款面向.NET开发人员的开源&#xff0c;跨平台机器学习框架&#xff0c;可以将自定义机器学习集成到.NET应用中。我们很开心地向您介绍我们在过去几个月中所做的工作。ML.NET:https://dotnet.microsof…

Andriod之提示java.lang.SecurityException: getDataNetworkTypeForSubscriber导致程序奔溃

1、问题 修改targetSdkVersion 33 适配Android13后4G网络环境被其它app拉起来提示这个异常 2、原因 我们定位到代码在这行函数 telephonyManager.getNetworkType()Android11 的权限有关,由于缺少该权限导致无法访问接口而提示安全异常 3、解决办法 方法1:我们直接申请RE…

[译]基于GPU的体渲染高级技术之raycasting算法

[译]基于GPU的体渲染高级技术之raycasting算法 PS&#xff1a;我决定翻译一下《Advanced Illumination Techniques for GPU-Based Volume Raycasting》。像我翻译其他资料一样&#xff0c;只按我的需要和观点来翻译。有的部分详细翻译&#xff0c;附加注解&#xff0c;有的部分…

【GIS风暴】什么是地理空间智能(Geospatial AI)?

人工智能(Artificial Intelligence,AI)已经成为新技术革命下一阶段的热词,也成为未来产业的驱动力量。使用智能算法,数据分类和智能预测、分析,AI在很多领域将有一系列的工具来帮助解决问题。 将AI用于GIS这一具体的领域的分析、方法和解决方案,就叫地理空间智能(Geos…

JavaScript 清除图片背景颜色 使之透明

主要JS /**清除图片背景颜色 **/ function removeImgBg(img) {//背景颜色 白色const rgba [255, 255, 255, 255];// 容差大小const tolerance 60;var imgData null;const [r0, g0, b0, a0] rgba;var r, g, b, a;const canvas document.createElement(canvas);const cont…