原文链接:https://leanpub.com/essentialtypescript/read#type-fundamentals
在Visual Studio Code中,打开 TypeScriptTodo 工程。 启动 tsc -w。
新建一个 test.ts 文件,这一章的代码需要在这个环境下练习。
1. JavaScript 类型
1.1. ES5 本身仅仅定义了六种类型:
boolean, number, string, null/undefined, object
其他的类型,如:Array,Function,RegExp等等,都是object的衍生品。
1.2. Object Prototype
prototypical inheritance
1.3. Object Literal
empty object:
{ }
把function作为属性的object:
var animal = {
name: "Fido",
species: "Dog",
age: 5,
speak: function() {
console.log('Woof!');
}
};
function makeTheAnimalSpeak(animal) {
animal.speak();
animal.speak = 1;
}
makeTheAnimalSpeak(animal);
第12行,给 speak 属性一个number 值,语法上是正确的,但这会导致代码可读性差,无法维护。TypeScript 出现的目的,主要是为了避免这类问题。
2. Type Inference
学习swift语言时,第一次遇到这个概念。 现在想想,let、var、arrow function、type inference 等等等等,现代的语言越来越像,严重同质化。前几天瞄了几眼Kotlin,也是惊人的相似。也许,这对程序员是个好事,学习成本低啊。
把鼠标指针放在变量上面,就能看到 TypeScript给我们推断出来的类型:
一旦我们在后续的代码中,违背了它推断出来的类型,如 animal.name = 1, TypeScript 就会认为这是一个错误。
TypeScript 还能做比较复杂的推断:
推断过程:
1. Data.now() 的返回值是number;
2. 所以,calculateAge() 的返回值是number;
3. 所以,animal.age 的类型是number。
信息不足时,TypeScript 无法推断出合适的类型:
any 是 TypeScript定义的一种类型,就是 “任意类型”。
当我们需要在TypeScript中使用动态类型时,可以借助于这个any类型。
3. 指定 JavaScript 类型
function totalLength(x,y:string) {
var total = x.length + y.lengt;
return total;
}
给 y 指定了string类型,TypeScript就能够发现第二行代码的拼写错误了。
改正拼写错误,TypeScript就不再抱怨了。但,这时,它还是不能推断出 totalLength() 的返回值类型。
function totalLength(x, y:string):number {
var total:number = x.length + y.length;
return total;
}
为什么要明确指定函数的返回值类型呢?增加可读性,避免以后改动函数体导致的不一致性。
function totalLength(x: any[], y:string):number {
var total:number = x.length + y.length;
return total;
}
x是array,y是string,都有length属性,这么写是合法的。
4. Union Types
function totalLength(x: (string | any[]), y:(string | any[])):number {
var total:number = x.length + y.length;
return total;
}
使用管道符号 ( | ),函数可以接受 union 类型。类似于逻辑操作符 “或” 。
type guard
function totalLength(x: (string | any[]), y:(string | any[])):number {
if(x instanceof Array) {
x.push('abc');
}
if(typeof x === 'string') {
x.substr(1);
}
var total:number = x.length + y.length;
return total;
}
上面两个 if 代码块就是type guard,有了 instanceof 和 typeof 操作符,TypeScript 可以推断出后续的代码是合法的。 如果把 x.push('abc') 拿到 if 块外面来,编译器会报错。
5. Function Overloads
这并不是真正的 overload,只是提供了多个function signature,我们无法为每种signature提供独立的函数体:
function totalLength(x: string, y:string): number
function totalLength(x: any[], y:any[]): number
function totalLength(x: (string | any[]), y:(string | any[])):number {
if(x instanceof Array) {
x.push('abc');
}
if(typeof x === 'string') {
x.substr(1);
}
var total:number = x.length + y.length;
return total;
}
当使用 totalLength() 时,编辑器可以提供上下文提示: