html转义字符_sql注入字符转义_ios url字符转义

作者 | 微软官方博客

译者 | 核子可乐

策划 | 小智

稿源|前端之巅

今天,微软在其官方博客宣布: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 对应版本;

安装 Visual Studio Code Insiders 版本;

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

l_using-newer-typescript-versions

配合 Sublime Text 3 使用 PackageControl。

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

Inference 与 Promise.all 迎来改进

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

interface Lion {

    roar(): void

}

interface Seal {

    singKissFromARose(): void

}

async function visitZoo(lionExhibit: Promise, 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 的性能问题。

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

我们还对编辑器方案中的文件重命名功能做出几项调整。根据 Visual Studio Code 团队提供的建议html转义字符,我们发现在执行文件重命名时,单是查明哪些导入语句需要更新就要耗去 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-error

console.log(47 * "octopus");

但下列代码:

// @ts-expect-error

console.log(1 + 1);

会导致错误:

Unused '@ts-expect-error' directive.

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

ts-ignore 还是 ts-expect-error?

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

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

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

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

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

在 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 还进一步提交了快速修复方案,旨在改善未调用函数检查功能的使用体验!

ios url字符转义_sql注入字符转义_html转义字符

编辑器改进

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

JavaScript 中的 CommonJS 自动补全

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

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

import * as fs from "fs";

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

const fs = require("fs");

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

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

代码操作保留换行符

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);

    }

}

sql注入字符转义_ios url字符转义_html转义字符

这就不对了——原本 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);

    }

}

html转义字符_ios url字符转义_sql注入字符转义

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

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

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

// before

let f1 = () => 42

// oops - not the same!

let f2 = () => { 42 }

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

sql注入字符转义_ios url字符转义_html转义字符

支持 “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 转义代码 (例如

2 >1

) 或者插入一个带有字符串字面值的表达式 (例如

2 {“>”} 1

)。

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

Unexpected token. Did you mean `{'>'}` or `>`?

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

例如:

let directions = <div>Navigate to: Menu Bar > Tools > Options</div>

// ~ ~

// Unexpected token. Did you mean `{'>'}` or `>`?

这条错误消息中还附带便捷的快速修复功能,感谢 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'.

限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688