参考资料:
一些有用的网址:
资源:
- 尚硅谷的TS代码、笔记:TS代码和代码.zip
安装:npm install -g typescript
编译:tsc hello.ts
优势是增强了编译器和IDE的功能,包括代码补全、接口提示、跳转到定义、重构等;
TS文件编译后生成JS文件,与检查相关的代码并未生成,这是因为TS只在编译时对代码进行检查,若有错误则直接报错,而在运行时与JS一样不对类型进行检查。编译即使报错,也会生成JS文件。
基础
原始数据类型
介绍5种基本数据类型在TS上的应用。
let isDone:boolean = false; // 布尔
let six:number = 6; // 数值
let notANumber: number = NaN;
let infinityNumber: number = Infinity;
let binaryLiteral: number = 0b1010; // ES6 中的二进制表示法
let octalLiteral: number = 0o744; // ES6 中的八进制表示法
// 非十进制编译后会编译为十进制
let myName:string = 'Joy'; // string
// 可用 void 表示没有任何返回值的函数:
// undefined 和 null 是所有类型的子类型, 可以赋值给所有类型, 但void不可以
let u: undefined = undefined; // undefined
let n: null = null; // null
let num:number = undefined // --right--
let num:number = void // --wrong--
任意值类型
任意值类型any
允许被赋予任何类型的值;
let anyNumber:any = 'seven';
anyNumber = 7;
可以访问任意值的任何属性和方法,返回的类型也是任意值。
未声明的变量,识别为任意值类型:
let something; // any
something = 'seven';
something = 7;
类型推论
定义变量时赋值,但没有指定类型,TS会依照类型推论的规则推断出一个类型。
let something = 'seven';
something = 7; // error报错
联合类型
联合类型表示变量取值可以为多种类型种的一种:
let item: string|number = 10; // 赋值时,会根据类型推论的规则推断出一个类型
item = 'seven';
只能访问联合类型共有的属性、方法:
function getLength(item:string|number):number{
return item.length;
} // error, length不是string和number的共有方法
描述对象 - 接口
可用来约束对象的“形状”,若无可选属性、任意属性,则形状需保持一致,属性不多不少:
interface Person{
name: string;
age: number;
}
let tom:Person = {
name: 'Tom';
age: 18;
}
// 可选属性:
interface Person{
name: string;
age?: number; // 表示属性是可选的
}
let tom:Person = {
name: 'Tom';
}
// 任意属性
interface Person{
name: string;
[propName:string]: any; // 表示允许有一个任意属性
}
let tom:Person = {
name: 'Tom';
sex: 'man';
}
// 一旦定义了任意属性,则确定属性和可选属性的类型必须是任意属性的类型的子集;
// 但有一种例外:number 类型的任意属性签名不会影响其他 string 类型的属性签名:
// 但 string类型的任意属性会影响其它。
// 可以定义任意属性为联合类型[propName:string]:string|number
只读属性
readonly
定义只读属性,那么该属性只有初始化时可被赋值。
interface Person{
readonly id: number;
age?: number;
}
let tom: person = {
if: 89757;
}
tom.id = 1000; // error
注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候。
数组的类型
「类型 + 方括号」表示法
数组的项中不允许出现其他的类型;
let nums: number[] = [1,2,3,4]
let list: any[] = ['one', 2, {}, [4,5]]
数组泛型
另一种表示方法;
let nums: Array<number> = [1,2,3,4]
用接口表示数组
但通常不这么做;更多用来表示类数组。
interface NumberArray{
[index: number]: number;
}
let nums: NumberArray = [1,2,3,4]
类数组
不能用数组表示,应该用接口来表示
interface IArguments{ // 这是TS定义好的类型
[index: number]: any;
length: number;
callee: Function;
}
函数的类型
JS中常见定义函数的两种方式:
function sum(a, b){ return a+b; } // 函数声明
let sum = function(a, b){ return a+b; } // 函数表达式
对应的TS类型定义为:
// 函数声明,调用时,传入参数的个数需要正确
function sum(a: number, b: number): number{ return a+b; }
// 函数表达式
let sum: (a:number,b:number)=>number = function (a:number, b:number):number{return a+b;}
// 注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>
还可以用接口定义函数形状:
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
return source.search(subString) !== -1;
}
可选参数
如何定义可选参数,一种方法与接口的可选属性类似,使用”?”:
function sum(a:number, b:number, c?:number): number{
if(c !== undefined)return a+b+c;
return a+b;
}
// 可选参数后面不允许再出现必需参数
参数默认值:TS会将添加了默认值的参数,识别为可选参数,这也是添加可选参数的另一种方法:
function sum(a:number, b:number, c:number = 5): number{
return a+b+c;
}
剩余参数
ES6中使用...rest
的方式获取函数的剩余参数,是一个数组,因此表示如下:
function myPush(array:number[], ...rest:number[]){
rest.forEach((item)=>{
array.push(item);
});
}
let a = [];
myPush(a, 1, 2, 3, 4);
重载
重载表示函数接收参数数量或类型不同时,做出不同的处理。
如输入123,返回321;输入’one’,返回’eno’。
// 使用联合类型实现,但有个缺点,即不能精确表达
function myReverse(n: string | number): string | number {
if (typeof n === 'number') {
return Number(n.toString().split('').reverse().join());
}
else if (typeof n === 'string') {
return n.split('').reverse().join();
}
}
// 使用重载,对比联合也就在前面加了两行函数定义
// TypeScript 会优先从最前面的函数定义开始匹配,所以优先将精确的定义放在前面
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
类型断言
断言的用途
- 将一个联合类型断言为其中一个类型
- 将一个父类断言为更加具体的子类
- 将任何一个类型断言为
any
:它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用 as any - 将
any
断言为一个具体的类型 - B兼容A或A兼容B,则可相互断言
双重断言
双重断言as any as Foo
,除非迫不得已,千万别用双重断言。类型断言VS类型转换
类型断言不会影响到变量的类型类型断言VS类型声明
类型断言VS泛型
声明文件
当你在编写TS代码时,需要使用第三方的JS库(.js文件),引入的时候编译器会提示各种报错,因为引用的JS文件没有各种声明,这时候就需要有一个声明文件来进行辅助,才能获得对应的代码补全、接口提示等功能。
如:需引用module-lib.js文件,则需要在同目录下有module-lib.d.ts文件(TS会自动使用),很多第三方库都会提供自己的声明文件。内置对象
很多JS内置对象都在TS定义好了类型。ECMAScript 的内置对象
DOM 和 BOM 的内置对象
TypeScript 核心库的定义文件
用 TypeScript 写 Node.js
需引入第三方声明文件:npm install @types/nodes--save-dev