TypeScript 2.6 在万圣节出现啦!不过不用怕,我们在这个版本中准备了很多好玩的东西。
如果你没有听说过 TypeScript,我可以简单介绍一下:它是通过添加可选的静态类型,建立在 JavaScript 最新版本之上的语言。这些类型不只是帮助捕捉拼写错误、逻辑错误这类的错误,他们也可以给你带来更好的工具像编辑自动补全,更方便的代码库导航,等等其他功能。最好的是,你不一定要写出你的类型注释 – TypeScript 经常可以为你推测出这些注释!
想学习更多 TypeScript 的知识, 你可以访问这个页面,但是如果你已经对 TypeScript 很熟悉了,想直接试试这个新版本,我们在 NuGet 上提供了下载,或者直接使用下面的 npm
命令:
npm install -g typescript
Visual Studio 2015 用户(更新到了第三版的用户)可以从这里安装 TypeScript 2.6。Visual Studio 2017 用户,使用 15.2 或者更高版本的,可以直接从这里安装。Visual Studio 2017 用户请确认已经阅读过怎样配置您的工程使用指定的 TypeScript 版本。
TypeScript 2.6 马上也会支持其他的编辑器。现在你可以配置 Visual Studio Code 和 Sublime Text 用上最新的版本。其他编辑器可以通过其他的途径用上 TypeScript 2.6 。
那现在就让我们看看 TypeScript 2.6 都给我们准备了什么吧!
--strictFunctionTypes
当比较签名的时候,那些使你的类型 callable 或 constructable – TypeScript 已经考虑到这两个返回类型和参数类型。
返回类型是很容易的 - 对于一个函数 f
可以被赋值为 g
, f
的返回类型必须赋值给 g
的返回类型。事实上,在这个比较中方向性不会被改变的,这被成为 covariance。
不管怎样,参数确实是另一个故事了,正确的道路是走完全相反的路。到底是怎么回事呢,我们来看一个小例子,这里我们把下面的 g
赋值给 f
:
interface Animal { animalProp: any };
interface Dog extends Animal { dogProp: any };
let f = (animal: Animal) => animal.animalProp;
let g = (dog: Dog) => dog.dogProp;
// Should this succeed?
f = g;
乍一看,我们可能会因为 Dog
被赋值给 Animal
,所以 g
被赋值给 f
,但事实上不是的。我们如果问问一些可替代性的问题,一切就变得清晰了:
(dog:Dog)=>any
的类型值被说成可以用来代替 (animal:Animal)=>any
,这样好吗?
Animal
能被用来替换 Dog
- 所以 Animal
是被赋值给 Dog
了吗?dogProp
。Dog
上的属性的时候,我们的函数只希望是 Animal
,这样对吗?所以说 g
不是被赋值给 f
,但是反过来正确吗?
(animal:Animal)=>any
的类型值被说成可以用来代替 (dog:Dog)=>any
,这样好吗?
Dog
能被用来替换 Animal
- 所以 Dog
是被赋值给 Animal
了吗?Animal
上的属性的时候,我们的函数只希望是 Dog
,这样对吗?请注意,在问 (animal:Animal)=>any
是否可赋值为 (dog:Dog)=>any
时,我们最终会问“狗”是否可赋值给动物。这种反向翻转被称为contravariance(逆变)。
虽然这种方法在大多数语言中都是适当的,但是很难使它与 JavaScript 广泛使用的方式相一致。像在 HTML DOM 层次结构中使用数组和描述方法,将会产生严格逆变的问题。例如,在 Array
类型中,其 pop
方法 返回了 T
,而且它的 push
方法 带走了 T
。如果 TypeScript 比较各函数参数逆变,它会使所有 T
上 数组_不变_
,因为 T
发生在协变和逆变的位置。换句话说, 数组
不会赋值给 数组
,这对于许多场景来说可能是很有挑战性的。
这就是为什么 TypeScript 双变地 或 双向地 比较参数。这意味着完全无关的类型会被捕捉到,但它意味着某些不好的问题可以见缝插针,当有足够的重叠的时候:
function makeLowerCase(s: string) {
return s.toLowerCase();
}
declare let foo: Promise<string | number>;
foo.then(makeLowerCase); // Whoops! TypeScript allows this, but `makeLowerCase` might get a `number`.
foo.then(makeLowerCase); // 是的!TypeScript 允许这样!但是 `makeLowerCase` 可能得到一个 `number`
这就是为什么在 TypeScript 2.6 中,我们给用户提供了一个收紧的方法 strictfunctiontypes
。在这种新的 严格
模式下,不来自方法的任何函数类型有相对比较严格逆变的参数。
这意味着上面代码将会失败,因为当我们试图用 (s:string)=>string
类型传递 makelowercase
到 then
,期望是 (onfulfilled:string|number)=>...
的类型函数的的时候,我们会翻转方向然后尝试评估 string|number
是否被赋值给 string
(这不是个案 – string
是 string|number
的子类)。不包括从检查方法允许 TypeScript 继续上述用例建模(如事件处理程序和简单的数组处理)虽然仍然需要严格检查。
协变和逆变 可能需要多一些彻底的解释才行。如果你愿意多读一些的话,Stephan Boyer 有一篇通俗易懂的文章给了一个合理的、高水平的解释。你也可以在 pull request 上了解到更多信息。这个短小精悍的版本是说,有了 --strictFunctionTypes
你就可以捕捉到更多的常见错误。
请记住,在严格模式 --strict
选项被开启的情况下,如果 --strictFunctionTypes
选项被开启,它将自动打开。这样可能会有一些坏处,所以如果要在严格模式开启的时候禁用这个检查,你可以在命令行中指定 --strictFunctionTypesfalse
,或者在 tsconfig.json
配置一下:
{
"compilerOptions": {
"strict": true,
"strictFunctionTypes": false
}
}
--locale
标志翻译 tsc
独立文件的编译器现在提供本地化(翻译后的)提示信息,当使用 --locale
选项的时候,大家可以在 npm 上下载。仅仅通过适当的语言标志 作为参数传给 TypeScript 编译器的 --locale
选项。如果该语言被支持,TypeScript将提供一个翻译的版本。
这意味着你可以或者中文的提示信息(简体中文使用 zh-CN
,繁体中文使用 zh-TW
):
tsc --pretty --locale zh-CN
bar.ts(1,1): error TS2362: 算术运算左侧必须是 "any"、、"number" 或枚举类型。
'hello' * 1
~~~~~~~
西班牙语:
$ tsc --pretty --locale es
foo.ts(1,1): error TS2362: La parte izquierda de una operación aritmética debe ser de tipo "any", "number" o un tipo enum.
'hello' * 1
~~~~~~~
日语:
$ tsc --pretty --locale ja
foo.ts(1,1): error TS2362: 算術演算の左辺には、'any' 型、'number' 型、または列挙型を指定してください。
'hello' * 1
~~~~~~~
俄罗斯语:
$ tsc --pretty --locale ru
foo.ts(1,1): error TS2362: Левый операнд арифметической операции должен иметь тип any, number или тип перечисления.
'hello' * 1
~~~~~~~
还有很多其他的语言支持,你可以阅读我们的编译器选项介绍页。
--watch
模式TypeScript 的 --watch
模式在模块更新时,会更多地根据增量去编译。给定一组更改的文件后, tsc
现在将会找出文件的有影响的部分。这意味着只有有影响的文件将经历一个树状变换流程(将代码从 TypeScript 编译到 ES2016、ES2015、ES5,到 ES3 的过程),以及发布流程(打印出编译后的文件本身)。对于非常大的代码库,大量使用 ECMAScript 的模块,这将会有非常大的提升。
如果您没有使用 --watch
模式,因为您依赖于另一个构建工具,那么好消息是我们打算为其他工具提供一个 API,以便他们也能从这个更改中获得一些相同的性能提升。Webpack、Gulp 和其他的 TypeScript 插件将会使用这个 API,我们希望在近期的插件发布中更新这些。
// @ts-ignore
隐藏文件中的报错历史上,我们已经避免了 TypeScript 隐藏报错,因为大多数情况下,用户想要可以通过更准确的申明文件或使用断言 any
解决。然而,随着时间的推移,我们看到了两个激进的例子:从 JavaScript 迁移到 TypeScript ,并克服了遗留代码里的类型检查。
有了 TypeScript 2.6 我们将给 TypeScript 带来 // @ts-ignore
注释功能。这些注释是一种轻量级的方法来抑制下一行中出现的任何错误。例如,在以下代码中,TypeScript 通常会报告 console.log
声明不可访问。在 TypeScript 2.6 中, // @ts-ignore
会完全忽略注释。
if (false) {
// @ts-ignore: 无法被执行的代码的报错
console.log("hello");
}
虽然这个功能是出于实用主义,但我们鼓励认真对待类型错误检查。我们的建议是有节制地使用隐藏注释功能。在你确实需要使用这些注释的情况下,我们建议像上面的例子一样,留一个为什么注释是被需要的解释。
我们对 TypeScript 上的投入不仅涉及语言和编译器。提高语言服务是 TypeScript 体验的核心。以下是您将在 Visual Studio 和Visual Studio Code 等代码编辑器中看到的一些改进。
any
TypeScript 现在可以通过 use-sites 来推断类型是隐式的 any
类型声明。
TypeScript 现在提供了从 JSDoc 注释添加参数的一个重构方式。
从一个旧的 JavaScript 代码库中迁移时,你可以使用这样的重构方式,还有隐式 any
的快速修复方法来让你的代码库更快迁移。
有时您可能会尝试使用一个装饰器而之前没有调用它。
值得庆幸的是,TypeScript 可以用一些基本的启发算法去指出这些场景,并可以提供一个有用的错误信息,并提供一个方便的快速修复方案,比如从 @Input
到 @Input()
。
@types
中安装编辑器不久将会提供一个快速修复方案来给没有类型化的引用安装类型定义。
有几个小的变化可能影响您的代码。您可以在我们的重大变化这篇文章中阅读更多关于他们,在升级的时候请记住这些。
--nounusedlocals
和 --nounusedparameters
配置中。
申明模块
)中,表达式现在不允许在 default
中输出。
number&string
, “foo”&42
等)当放置在一个联合体中时将简化为 never
。
lib.d.ts
中生成了。
至于大家意见很大的 getSymbolDisplayBuilder
API,现在已经不再使用了。对于简单的场景下,你应该能够移动到 TypeChecker#symbolToString
。在更高级的场景下,我们计划在TypeScript 2.7中把 symbolToString
升级到全功能的 SymbolDisplayBuilder
。在未来的 TypeScript 2.7 中,我们将删除 getSymbolDisplayBuilder
。
获取更多完整的关于 TypeScript 2.6 图片,您可以访问 What’s New in TypeScript 的 wiki 页面。您也可以看我们版本更新计划表 the TypeScript Roadmap。
不用多说,但是如果你在使用的时候遇到任何问题,希望您可以在我们的问题反馈页面反馈一下。如果您喜欢这个版本,也可以在 Twitter 上使用 #iHeartTypeScript 标签发推让我们知道。
我们希望这个版本的 TypeScript 易于使用,带来更多类型安全性,使您的工作更有效率,并且使用起来更有乐趣。
Happy Hacking!
往期精选文章 |
---|
使用虚拟dom和JavaScript构建完全响应式的UI框架 |
扩展 Vue 组件 |
使用Three.js制作酷炫无比的无穷隧道特效 |
一个治愈JavaScript疲劳的学习计划 |
全栈工程师技能大全 |
WEB前端性能优化常见方法 |
一小时内搭建一个全栈Web应用框架 |
干货:CSS 专业技巧 |
四步实现React页面过渡动画效果 |
让你分分钟理解 JavaScript 闭包 |
小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。