TypeScript 1.6 增加了一个新的在 if 语句中收窄变量类型的方式, 作为对 typeof 和 instanceof 的补充. 用户定义的类型收窄函数的返回值类型标注形式为 x is T, 这里 x 是函数声明中的形参, T 是任何类型. 当一个用户定义的类型收窄函数在 if 语句中被传入某个变量执行时, 该变量的类型会被收窄到 T.
function extend<T, U>(first: T, second: U): T & U {
let result = <T & U> {};
for (let id in first) {
result[id] = first[id];
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
result[id] = second[id];
}
}
return result;
}
var x = extend({ a: "hello" }, { b: 42 });
var s = x.a;
var n = x.b;
type LinkedList<T> = T & { next: LinkedList<T> };
interface Person {
name: string;
}
var people: LinkedList<Person>;
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;
interface A { a: string }
interface B { b: string }
interface C { c: string }
var abc: A & B & C;
abc.a = "hello";
abc.b = "hello";
abc.c = "hello";
function f() {
if (true) {
interface T { x: number }
let v: T;
v.x = 5;
}
else {
interface T { x: string }
let v: T;
v.x = "hello";
}
}
interface Point {
x: number;
y: number;
}
function getPointFactory(x: number, y: number) {
class P {
x = x;
y = y;
}
return P;
}
var PointZero = getPointFactory(0, 0);
var PointOne = getPointFactory(1, 1);
var p1 = new PointZero();
var p2 = new PointZero();
var p3 = new PointOne();
function f3() {
function f<X, Y>(x: X, y: Y) {
class C {
public x = x;
public y = y;
}
return C;
}
let C = f(10, "hello");
let v = new C();
let x = v.x; // number
let y = v.y; // string
}
let Point = class {
constructor(public x: number, public y: number) { }
public length() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
};
var p = new Point(3, 4); // p has anonymous class type
console.log(p.length());
// 继承内建类
class MyArray extends Array<number> { }
class MyError extends Error { }
// 继承表达式类
class ThingA {
getGreeting() { return "Hello from A"; }
}
class ThingB {
getGreeting() { return "Hello from B"; }
}
interface Greeter {
getGreeting(): string;
}
interface GreeterConstructor {
new (): Greeter;
}
function getGreeterBase(): GreeterConstructor {
return Math.random() >= 0.5 ? ThingA : ThingB;
}
class Test extends getGreeterBase() {
sayHello() {
console.log(this.getGreeting());
}
}
abstract class Base {
abstract getThing(): string;
getOtherThing() { return 'hello'; }
}
let x = new Base(); // 错误, 'Base' 是抽象的
// 错误, 必须也为抽象类, 或者实现 'getThing' 方法
class Derived1 extends Base { }
class Derived2 extends Base {
getThing() { return 'hello'; }
foo() {
super.getThing();// 错误: 不能调用 'super' 的抽象方法
}
}
var x = new Derived2(); // 正确
var y: Base = new Derived2(); // 同样正确
y.getThing(); // 正确
y.getOtherThing(); // 正确
type Lazy<T> = T | (() => T);
var s: Lazy<string>;
s = "eager";
s = () => "lazy";
interface Tuple<A, B> {
a: A;
b: B;
}
type Pair<T> = Tuple<T, T>;
var x: { foo: number };
x = { foo: 1, baz: 2 }; // 错误, 多余的属性 `baz`
var y: { foo: number, bar?: number };
y = { foo: 1, baz: 2 }; // 错误, 多余或者拼错的属性 `baz`
var x: { foo: number, [x: string]: any };
x = { foo: 1, baz: 2 }; // 现在 `baz` 匹配了索引签名
function *g(): Iterable<string> {
for (var i = 0; i < 100; i++) {
yield ""; // string 可以赋值给 string
}
yield * otherStringGenerator(); // otherStringGenerator 必须可遍历, 并且元素类型需要可赋值给 string
}
function *g() {
for (var i = 0; i < 100; i++) {
yield ""; // 推导出 string
}
yield * otherStringGenerator(); // 推导出 otherStringGenerator 的元素类型
}
var p: Promise<number> = /* ... */;
async function fn(): Promise<number> {
var i = await p; // 暂停执行直到 'p' 得到结果. 'i' 的类型为 "number"
return 1 + i;
}
var a = async (): Promise<number> => 1 + await p; // 暂停执行.
var a = async () => 1 + await p; // 暂停执行. 使用 --target ES6 选项编译时返回值类型被推断为 "Promise<number>"
var fe = async function(): Promise<number> {
var i = await p; // 暂停执行知道 'p' 得到结果. 'i' 的类型为 "number"
return 1 + i;
}
class C {
async m(): Promise<number> {
var i = await p; // 暂停执行知道 'p' 得到结果. 'i' 的类型为 "number"
return 1 + i;
}
async get p(): Promise<number> {
var i = await p; // 暂停执行知道 'p' 得到结果. 'i' 的类型为 "number"
return 1 + i;
}
}
npm install -g typescript@next
declare class Foo {
public x : number;
}
interface Foo {
y : string;
}
function bar(foo : Foo) {
foo.x = 1; // 没问题, 在类 Foo 中有声明
foo.y = "1"; // 没问题, 在接口 Foo 中有声明
}
function isCat(a: any): a is Cat {
return a.name === 'kitty';
}
var x: Cat | Dog;
if(isCat(x)) {
x.meow(); // 那么, x 在这个代码块内是 Cat 类型
}