TypeScript 1.8
Type 参数作为约束
使用 TypeScript 1.8,可以使用类型参数约束从相同的类型参数列表中引用类型参数。以前这是一个错误。这种能力通常被称为 F-Bounded Polymorphism。
示例
function assign<T extends U, U>(target: T, source: U): T {
for (let id in source) {
target[id] = source[id];
}
return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
assign(x, { b: 10, d: 20 });
assign(x, { e: 0 }); // Error
控制流量分析错误
TypeScript 1.8 引入了控制流分析来帮助捕捉用户倾向于遇到的常见错误。请阅读以获取更多详细信息,并查看这些错误的实际操作:
无法访问的代码
保证不会在运行时执行的语句现在可以正确标记为不可达代码错误。例如,下面的语句无条件的return
,throw
,break
或continue
语句被认为是不可到达的。使用--allowUnreachableCode
禁用可达代码检测和报告。
示例
以下是一个无法访问的代码错误的简单示例:
function f(x) {
if (x) {
return true;
}
else {
return false;
}
x = 0; // Error: Unreachable code detected.
}
此功能捕获的更常见的错误是在return
语句后添加换行符:
function f() {
return // Automatic Semicolon Insertion triggered at newline
{
x: "string" // Error: Unreachable code detected.
}
}
由于 JavaScript 在行尾自动终止return
语句,因此对象字面量变为块。
未使用的标签
未使用的标签也被标记。就像无法访问的代码检查一样,这些默认情况下都会打开; 用于--allowUnusedLabels
停止报告这些错误。
示例
loop: while (x > 0) { // Error: Unused label.
x++;
}
隐式返回
具有不返回 JS 值的代码路径的函数隐式返回undefined
。这些现在可以被编译器标记为隐式返回。该检查默认关闭 ; 使用--noImplicitReturns
打开它。
示例
function f(x) { // Error: Not all code paths return a value.
if (x) {
return false;
}
// implicitly returns `undefined`
}
案例条款落后
在 case 子句非空的 switch 语句中,TypeScript 可以报告错误情况。该检查默认关闭,可以使用启用--noFallthroughCasesInSwitch
。
示例
有了--noFallthroughCasesInSwitch
这个例子会触发一个错误:
switch (x % 2) {
case 0: // Error: Fallthrough case in switch.
console.log("even");
case 1:
console.log("odd");
break;
}
但是,在下面的示例中,由于落空情况为空,因此不会报告错误:
switch (x % 3) {
case 0:
case 1:
console.log("Acceptable");
break;
case 2:
console.log("This is *two much*!");
break;
}
React 中的无状态函数组件
TypeScript 现在支持无状态函数组件。这些是轻松构成其他组件的轻量级组件:
// Use parameter destructuring and defaults for easy definition of 'props' type
const Greeter = ({name = 'world'}) => <div>Hello, {name}!</div>;
// Properties get validated
let example = <Greeter name='TypeScript 1.8' />;
对于这个功能和简化的道具,一定要使用 react.d.ts 的最新版本。
React中简化的props
类型管理
在带有最新版本 react.d.ts 的 TypeScript 1.8 中(见上),我们也大大简化了props
类型的声明。
特别:
- 您不再需要显式声明
ref
和key
或extend React.Props
ref
和key
性能会出现正确的类型上的所有组件
- 该
ref
属性在无状态函数组件的实例中被正确禁止
从模块中增加全局/模块范围
用户现在可以声明他们想要创建的任何扩展,或者任何其他使用者已经创建的扩展到现有模块。模块增强看起来像普通的旧环境模块声明(即declare module "foo" { }
语法),并且直接嵌套在您自己的模块中,或者直接嵌套在另一个顶级环境外部模块中。
此外,TypeScript 还具有表单全局增强的概念declare global { }
。这允许模块增加全局类型(Array
如有必要)。
模块扩充的名称使用与模块说明符相同的一组规则import
和export
声明来解决。模块扩充中的声明以与在同一文件中声明的方式相同的方式与任何现有声明合并。
模块增强和全局增强都不能将新项添加到顶层作用域 - 它们只能“修补”现有的声明。
示例
这里map.ts
可以声明它将在内部修补Observable
类型observable.ts
并将map
方法添加到它。
// observable.ts
export class Observable<T> {
// ...
}
// map.ts
import { Observable } from "./observable";
// Create an augmentation for "./observable"
declare module "./observable" {
// Augment the 'Observable' class definition with interface merging
interface Observable<T> {
map<U>(proj: (el: T) => U): Observable<U>;
}
}
Observable.prototype.map = /*...*/;
// consumer.ts
import { Observable } from "./observable";
import "./map";
let o: Observable<number>;
o.map(x => x.toFixed());
同样,全局范围可以通过使用declare global
声明的模块进行扩充:
示例
// Ensure this is treated as a module.
export {};
declare global {
interface Array<T> {
mapToNumbers(): number[];
}
}
Array.prototype.mapToNumbers = function () { /* ... */ }
字符串文字类型
API 对于某些值期望一组特定的字符串并不罕见。例如,考虑一个 UI 库,它可以在控制动画的“缓动”的同时在屏幕上移动元素。
declare class UIElement {
animate(options: AnimationOptions): void;
}
interface AnimationOptions {
deltaX: number;
deltaY: number;
easing: string; // Can be "ease-in", "ease-out", "ease-in-out"
}
但是,这很容易出错 - 没有任何东西阻止用户意外地拼错其中一个有效缓动值:
// No errors
new UIElement().animate({ deltaX: 100, deltaY: 100, easing: "ease-inout" });
使用 TypeScript 1.8,我们引入了字符串文字类型。这些类型的书写方式与字符串文字相同,但是在类型位置。
用户现在可以确保类型系统会捕获这样的错误。这里是我们新AnimationOptions
使用的字符串文字类型:
interface AnimationOptions {
deltaX: number;
deltaY: number;
easing: "ease-in" | "ease-out" | "ease-in-out";
}
// Error: Type '"ease-inout"' is not assignable to type '"ease-in" | "ease-out" | "ease-in-out"'
new UIElement().animate({ deltaX: 100, deltaY: 100, easing: "ease-inout" });
改进的联合/交叉类型推断
TypeScript 1.8改进了涉及源和目标边的类型推断,它们都是联合或交集类型。例如,从当推断string | string[]
到string | T
,我们减少类型string[]
和T
,从而推断string[]
为T
。
示例
type Maybe<T> = T | void;
function isDefined<T>(x: Maybe<T>): x is T {
return x !== undefined && x !== null;
}
function isUndefined<T>(x: Maybe<T>): x is void {
return x === undefined || x === null;
}
function getOrElse<T>(x: Maybe<T>, defaultValue: T): T {
return isDefined(x) ? x : defaultValue;
}
function test1(x: Maybe<string>) {
let x1 = getOrElse(x, "Undefined"); // string
let x2 = isDefined(x) ? x : "Undefined"; // string
let x3 = isUndefined(x) ? "Undefined" : x; // string
}
function test2(x: Maybe<number>) {
let x1 = getOrElse(x, -1); // number
let x2 = isDefined(x) ? x : -1; // number
let x3 = isUndefined(x) ? -1 : x; // number
}
--outFil
连接AMD
和System
模块
指定--outFile
连接--module amd
或--module system
将连接编译中的所有模块到包含多个模块闭包的单个输出文件中。
将根据每个模块的相对位置计算模块名称rootDir
。
示例
// file src/a.ts
import * as B from "./lib/b";
export function createA() {
return B.createB();
}
// file src/lib/b.ts
export function createB() {
return { };
}
结果是:
define("lib/b", ["require", "exports"], function (require, exports) {
"use strict";
function createB() {
return {};
}
exports.createB = createB;
});
define("a", ["require", "exports", "lib/b"], function (require, exports, B) {
"use strict";
function createA() {
return B.createB();
}
exports.createA = createA;
});
支持default
与 SystemJS 进行互操作
像 SystemJS 这样的模块加载程序将 CommonJS 模块封装起来,然后作为default
ES6 导入进行公开。这使得不可能在模块的 SystemJS 和 CommonJS 实现之间共享定义文件,因为根据加载器,模块形状看起来不同。
设置新的编译器标志--allowSyntheticDefaultImports
表明模块加载器执行某种在导入的 .ts 或 .d.ts 中未指示的合成默认导入成员创建。编译器会推断出default
具有整个模块本身形状的导出。
系统模块默认打开此标志。
允许捕获let
/ const
循环
以前是 TypeScript 1.8 现在支持的错误。let
/ const
循环内的声明和函数捕获现在发射到正确匹配let
/ const
新鲜语义。
示例
let list = [];
for (let i = 0; i < 5; i++) {
list.push(() => i);
}
list.forEach(f => console.log(f()));
被编译为:
var list = [];
var _loop_1 = function(i) {
list.push(function () { return i; });
};
for (var i = 0; i < 5; i++) {
_loop_1(i);
}
list.forEach(function (f) { return console.log(f()); });
并在结果中
0
1
2
3
4
改进了对for..in
语句的检查
以前,for..in
变量的类型被推断为any
; 这允许编译器忽略for..in
正文中的无效用途。
从 TypeScript 1.8 开始:
- 在
for..in
语句中声明的变量的类型是隐含的string
。
- 当具有数字索引签名类型
T
(例如数组)的对象通过包含具有数字索引签名并且没有字符串索引签名(又如数组)的对象for..in
的包含for..in
语句的变量进行索引时,生成的值是类型的T
示例
var a: MyObject[];
for (var x in a) { // Type of x is implicitly string
var obj = a[x]; // Type of obj is MyObject
}
模块现在发布了"use strict";
序言
根据 ES6,模块始终在严格模式下进行解析,但对于非ES6目标,这在生成的代码中不受重视。从 TypeScript 1.8 开始,发射模块始终处于严格模式。在大多数代码中,这不应该有任何明显的变化,因为 TS 在编译时将最严格的模式错误视为错误,但这意味着一些过去在 TS 代码中运行时以静默方式失败的东西,比如赋值NaN
,现在将大声地失败。您可以参考严格模式下的 MDN 文章,了解严格模式和非严格模式之间差异的详细清单。
包含.js
文件--allowJs
通常在您的项目中有外部源文件,可能不会在 TypeScript 中创作。或者,您可能正在将 JS 代码库转换为 TS,但仍希望将所有 JS 代码与新 TS 代码的输出捆绑到一个文件中。
.js
现在允许文件作为输入tsc
。TypeScript 编译器检查输入.js
文件的语法错误,并根据--target
和--module
标志发出有效输出。输出也可以与其他.ts
文件结合使用。源.js
文件仍然像.ts
文件一样为文件生成。
自定义 JSX 工厂使用 --reactNamespace
--reactNamespace <JSX factory Name>
一起传递--jsx react
允许使用默认的React
不同 JSX 工厂。
新的工厂名称将用于调用createElement
和__spread
功能。
示例
import {jsxFactory} from "jsxFactory";
var div = <div>Hello JSX!</div>
编译:
tsc --jsx react --reactNamespace jsxFactory --m commonJS
结果是:
"use strict";
var jsxFactory_1 = require("jsxFactory");
var div = jsxFactory_1.jsxFactory.createElement("div", null, "Hello JSX!");
this
型卫士
TypeScript 1.8将用户定义的类型保护函数扩展到类和接口方法。
this is T
现在是类和接口中方法的有效返回类型注释。当用于类型缩减位置(例如if
语句)时,调用表达式目标对象的类型将缩小到T
。
示例
class FileSystemObject {
isFile(): this is File { return this instanceof File; }
isDirectory(): this is Directory { return this instanceof Directory;}
isNetworked(): this is (Networked & this) { return this.networked; }
constructor(public path: string, private networked: boolean) {}
}
class File extends FileSystemObject {
constructor(path: string, public content: string) { super(path, false); }
}
class Directory extends FileSystemObject {
children: FileSystemObject[];
}
interface Networked {
host: string;
}
let fso: FileSystemObject = new File("foo/bar.txt", "foo");
if (fso.isFile()) {
fso.content; // fso is File
}
else if (fso.isDirectory()) {
fso.children; // fso is Directory
}
else if (fso.isNetworked()) {
fso.host; // fso is networked
}
官方 TypeScript NuGet 包
从 TypeScript 1.8 开始,官方 NuGet 包可用于 Typescript Compiler(tsc.exe
)以及 MSBuild 集成(Microsoft.TypeScript.targets
和Microsoft.TypeScript.Tasks.dll
)。
稳定的软件包可在这里找到:
- TypeScript-Preview来自
tsc
我们的漂亮的错误信息我们明白,大量的单色输出在眼睛上可能有点困难。颜色可以帮助辨别哪里的消息开始和结束,而这些视觉线索是重要的,当错误输出得到overwhelming.By刚好路过的--pretty
命令行选项,打字稿给人以情境更加丰富多彩输出何处事情会出错。
JSX的彩色化在VS 2015With打字稿1.8码,JSX标签现在分类和彩色在Visual Studio 2015年
的分类可以通过改变字体和颜色设置为进一步定制VB XML
通过颜色和字体设置Tools
- > Options
- > Environment
- > Fonts and Colors
PAGE电泳--project
(-p
)标志现在可以接受任何文件路径--project
命令行选项最初只能将路径引导到包含a的文件夹tsconfig.json
。鉴于构建配置的不同场景,允许--project
指向任何其他兼容的JSON文件是有意义的。例如,用户可能希望针对节点5使用CommonJS模块ES2015,而针对浏览器的ES515使用AMD模块。通过这项新工作,用户可以轻松管理两个独立的构建目标tsc
,而无需执行诸如将tsconfig.json
文件放置在单独目录中的黑客解决方法。如果给定目录,旧行为仍然保持不变 - 编译器将尝试在目录名为tsconfig.json
.Allow在tsconfig.json中的注释总是很高兴能够记录您的配置!tsconfig.json
现在接受单行和多行注释{“compilerOptions”:{“target”:“ES2015”,//在节点v5上运行,yaay!“sourceMap”:true //使调试变得更容易},/ * *排除文件* /“exclude”:[“file.d.ts”]}支持输出到IPC驱动文件TypeScript 1.8允许用户将--outFile
参数用于特殊文件系统实体(如命名管道,设备等)。例如,在许多类Unix系统上,标准输出流可通过文件/dev/stdout
.tsc foo.ts --outFile / dev / stdout访问。可用于在命令作为一个例子,我们可以将我们发出的JavaScript导入一个漂亮的打印机,比如pretty-js:tsc foo。ts --outFile / dev / stdout | tsconfig.json
pretty-js 在Visual Studio 2015TypeScript 1.8允许的支持tsconfig.json
所有项目类型的文件。这包括ASP.NET v4项目,控制台应用程序和带有TypeScript项目类型的Html应用程序。此外,您不再限制为单个tsconfig.json
文件,但可以添加多个文件,并且每个文件都将作为项目的一部分构建。这使您无需使用多个不同的项目分开你的应用程序的不同部分的配置。
当您添加我们也禁用项目属性页tsconfig.json
文件。这意味着所有配置更改都必须在tsconfig.json
文件本身中完成。有一些限制
- 如果添加
tsconfig.json
文件,则不会编译不被视为该上下文一部分的 TypeScript 文件。
- Apache Cordova Apps 仍然具有单个
tsconfig.json
文件的现有限制,该文件必须位于根目录或scripts
文件夹中。
- 大多数项目类型没有
tsconfig.json
模板。
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com