TypeScript 1.4

联合类型

概览

联合类型是描述一个可能是几个类型之一的值的有效方式. 举例来说, 你可能会有一个 API 用于执行一个 commandlinestring, string[] 或者是返回值为 string 的函数的程序. 现在可以这样写:

  1. interface RunOptions {
  2. program: string;
  3. commandline: string[]|string|(() => string);
  4. }

对联合类型的赋值非常直观 — 任何可以赋值给联合类型中任意一个类型的值都可以赋值给这个联合类型:

  1. var opts: RunOptions = /* ... */;
  2. opts.commandline = '-hello world'; // 没问题
  3. opts.commandline = ['-hello', 'world']; // 没问题
  4. opts.commandline = [42]; // 错误, number 不是 string 或 string[]

当从联合类型中读取时, 你可以看到联合类型中各类型共有的属性:

  1. if (opts.length === 0) { // 没问题, string 和 string[] 都有 'length' 属性
  2. console.log("it's empty");
  3. }

使用类型收窄, 你可以方便的使用具有联合类型的变量:

  1. function formatCommandline(c: string|string[]) {
  2. if (typeof c === 'string') {
  3. return c.trim();
  4. } else {
  5. return c.join(' ');
  6. }
  7. }

更严格的泛型

结合联合类型可以表示很多种类型场景, 我们决定让某些泛型调用更加严格. 之前, 以下的代码能出人意料地无错通过编译:

  1. function equal<T>(lhs: T, rhs: T): boolean {
  2. return lhs === rhs;
  3. }
  4. // 过去: 无错误
  5. // 现在: 错误, 'string' 和 'number' 间没有最佳共有类型
  6. var e = equal(42, 'hello');

而通过联合类型, 你现在可以在函数声明或者调用的时候指明想要的行为:

  1. // 'choose' 函数的参数类型必须相同
  2. function choose1<T>(a: T, b: T): T { return Math.random() > 0.5 ? a : b }
  3. var a = choose1('hello', 42); // 错误
  4. var b = choose1<string|number>('hello', 42); // 正确
  5. // 'choose' 函数的参数类型不需要相同
  6. function choose2<T, U>(a: T, b: U): T|U { return Math.random() > 0.5 ? a : b }
  7. var c = choose2('bar', 'foo'); // 正确, c: string
  8. var d = choose2('hello', 42); // 正确, d: string|number

更好的类型接口

联合类型也允许了数组或者其他地方有更好的类型接口, 以便一个集合中可能有多重类型.

  1. var x = [1, 'hello']; // x: Array<string|number>
  2. x[0] = 'world'; // 正确
  3. x[0] = false; // 错误, boolean 不是 string 或 number

let 声明

在 JavaScript 中, var 声明会被 “提升” 到它们所在的作用域. 这可能会导致一些令人疑惑的问题:

  1. console.log(x); // 本意是在这里写 'y'
  2. /* 当前代码块靠后的位置 */
  3. var x = 'hello';

ES6 的关键字 let 现在在 TypeScript 中得到支持, 声明变量获得了更直观的块级语义. 一个 let 变量只能在它声明之后被引用, 其作用域被限定于它被声明的句法块:

  1. if (foo) {
  2. console.log(x); // 错误, 在声明前不能引用 x
  3. let x = 'hello';
  4. } else {
  5. console.log(x); // 错误, x 在当前块中没有声明
  6. }

let 仅在编译到 ECMAScript 6 时被支持 (--target ES6).

const 声明

另外一种在 TypeScript 中被支持的新的 ES6 声明类型是 const. 一个 const 变量不能被赋值, 并且在声明的时候必须被初始化. 这可以用在你声明和初始化后不希望值被改变时:

  1. const halfPi = Math.PI / 2;
  2. halfPi = 2; // 错误, 不能赋值给一个 `const`

const 仅在编译到 ECMAScript 6 时被支持 (--target ES6).