参考资料:
一些有用的网址:
资源:
- 尚硅谷的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; // undefinedlet n: null = null; // nulllet num:number = undefined // --right--let num:number = void // --wrong--
任意值类型
任意值类型any允许被赋予任何类型的值;
let anyNumber:any = 'seven';anyNumber = 7;
可以访问任意值的任何属性和方法,返回的类型也是任意值。
未声明的变量,识别为任意值类型:
let something; // anysomething = '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
