TypeScript-1
一、基础
1. 原始数据类型:boolean,number,string,undefined,null,Symbol
let isDone:boolean=true; let num:number=6; let str:string='asd'; let u:undefined=undefined; let n:null=null; // 空值 ,用void表示没有任何返回值的函数 function test():void{ alert('122'); } // void 类型的变量只能赋值为 undefined 和 null let unusable:void=undefined; // undefined,null是所有类型的子类型,可以赋值给其他类型的变量 num=null; console.log(num);//null
2.任意值
任意值用来表示允许赋值为任意类型
//1. any类型,允许被赋值为任意类型, let num:any=7; num='123'; // 2.声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值。 let obj:any={}; obj.name='11' console.log(obj.name); // 3.变量如果在声明的时候,未指定其类型,会被识别为任意值类型 let a; a='bbb'; a=1111;//success let str='aaa'; str=123;//error 类型错误
3. 类型推论
如果没有明确的指定类型,TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
let str='aaaaa';//等价于 let str:string='aaaaa'; str=123;//error // 如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查: let num; num='aaa'; num=111;//success
4.联合类型
取值可以为多种类型的一种
// 1.联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型: let str:string|number; str='abc'; console.log(str.length);//3 str=123; console.log(str.length);//error: Property 'length' does not exist on type 'number' //2. 只能访问此联合类型的所有类型里共有的属性或方法: function test(params:string|number):string{ return params.toString(); }
5.对象的类型--接口
使用接口来定义对象的类型
接口:可用于对类的一部分行为进行抽象,也用对 对象的形状进行描述
//1.接口一般首字母大写,赋值的时候,变量的形状必须和接口的形状保持一致 interface Person{ name:string; age:number; } let test:Person={ name:'sy', age:12 } // 2.可选属性 ?:属性可以不存在,但是不允许添加未定义的属性 interface Person{ name:string; age?:number; } let test:Person={ name:'123', color:'red'//error ... 'color' does not exist in type 'Person'. } // 3.任意属性 interface Person{ name:string; age?:number; [propName:string]:any; } let test:Person={ name:'sy', color:'red' } // // 一旦定义了任意属性,那么确定属性和可选属性都必须是它的子属性: interface Person1{ name:string; age?:number; [propName:string]:string;//error:任意属性的值允许是 string,但是可选属性 age 的值却是 number,number 不是 string 的子属性,所以报错了 } // 4.只读属性:readonly interface Person{ readonly id:number; name:string; age?:number; [prop:string]:any; } let test:Person={ id:123, name:'sy', sex:'woman' } test.id=11;//error:Cannot assign to 'id' because it is a constant or a read-only property. // 只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候 let person:Person={ name:'aa',// error:Property 'id' is missing in type '{ name: string }' } person.id=11;//error:Cannot assign to 'id' because it is a constant or a read-only property.
6.数组的类型
//1. 使用「类型 + 方括号」来表示数组 let arr:number[]=[1,2,3]; // 数组中不允许出现其他类型 let arr1:number[]=[1,2,3,'a'];//error: Type 'string' is not assignable to type 'number'. let arr2:(number|string)[]=[1,2,3,'a'];//联合类型 // 2.使用数组泛型 Array<elemType> 来表示数组: let arr:Array<number>=[1,2,3]; // 3.用接口表示数组 interface NumberArray{ [index:number]:number; } let arr1:NumberArray=[1,2,3]; // 4.any 表示数组中允许出现任意类型 let list:any=[1,'asas',{name:'sy'}]; // 5.类数组 // 常见的类数组都有自己的接口定义,如 IArguments, NodeList, HTMLCollection 等: function sum(){ let args:IArguments=arguments; let arr:number[]=arguments;//error:Property 'push' is missing in type 'IArguments'. }
7.函数的类型
// 1.函数声明 // 参数必须相同 function sum(x:number,y:number):number{ return x+y; } sum(1,2); sum(1,2,3);//error: Expected 2 arguments, but got 3. // 2.函数表达式 // 在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。 let sum:(x:number,y:number)=>number=function(x:number,y:number):number{ return x+y; } // 3.用接口来定义函数的形状 interface PersonFun{ (name:string,age:number):boolean } let test:PersonFun; test=function(name:string,age:number):boolean{ return age>10; } // 4.可选参数? // 可选参数必须接在必需参数后面 function sum( x:number,y?:number):boolean{ return y?true:false; } sum(1,2);//true sum(1);//false // 5.参数默认值 function test(name:string,age:number=10){ return name+age; } test('sy');//"sy10" // 6.剩余参数: ...rest 的方式获取函数中的剩余参数 function push(arr,...items){ items.forEach((item)=>{ arr.push(item); }) } let arr=[]; push(arr,1,3,4,5);// [1, 3, 4, 5] // 7.重载:重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。 // 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(''); } } let a=reverse(123);//321 let b=reverse('hello');//"olleh"
8.类型断言
类型断言(Type Assertion)可以用来手动指定一个值的类型。
// 语法:<类型>值 或 值 as 类型 function getLength(param:string|number){ if((<string>param).length){ return (<string>param).length }else{ return param.toString().length; } } // 类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的 function toBoolean(param:string|number):boolean{ return <boolean> param;//error: Type 'string | number' cannot be converted to type 'boolean' }
9.声明文件
当使用第三方库时,我们需要引用它的声明文件。
// 1.声明语句 // 使用 declare 关键字来定义它的类型, declare var jQuery: (selector: string) => any; jQuery('#foo'); // 2.声明文件 // 通常我们会把类型声明放到一个单独的文件中,这就是声明文件: // jQuery.d.ts declare var jQuery: (string) => any; // 然后在使用到的文件的开头,用「三斜线指令」表示引用了声明文件: /// <reference path="./jQuery.d.ts" /> jQuery('#foo'); // 3.第三方声明文件 // TypeScript 2.0 推荐使用 @types 来管理。 // @types 的使用方式很简单,直接用 npm 安装对应的声明模块即可,以 jQuery 举例: npm install @types/jquery --save-dev
10.内置对象
内置对象是指根据标准在全局作用域上存在的对象。 里的标准是指 ECMAScript 和其他环境(比如 DOM)的标准。
// 1.ECMAScript 的内置对象 // Boolean、Error、Date、RegExp 等。 let b: Boolean = new Boolean(1); let e: Error = new Error('Error occurred'); let d: Date = new Date(); let r: RegExp = /[a-z]/; // 2.DOM 和 BOM 的内置对象 // Document、HTMLElement、Event、NodeList 等。 let body: HTMLElement = document.body; let allDiv: NodeList = document.querySelectorAll('div'); document.addEventListener('click', function(e: MouseEvent) { // Do something }); // 3.TypeScript 核心库的定义文件 // 定义了所有浏览器环境需要用到的类型,并且是预置在 TypeScript 中的 // 4.用 TypeScript 写 Node.js // Node.js 不是内置对象的一部分,如果想用 TypeScript 写 Node.js,则需要引入第三方声明文件: npm install @types/node --save-dev