简介
typescript是javascript的一个超集,主要提供了系统类型和对es6的支持,它是由Microsoft开发,代码开源在github
- 出现的原因:解决js弱语言的特性
- typescript是编辑性语言,将ts通过编辑变成js代码
- js是解释性语言
- 编译后的ts可以运行在任何服务器、浏览器
为何选择ts
- 增加了代码的可读性和可维护性
- 非常包容(例如:编译过程中出现了错误,还是可以继续编译成js,并且编译后的js可以正常的运行)
- 拥有活跃的社区
安装使用ts
- 全局安装 npm install -g typescript
- 编译文件 tsc greeter.ts
- 约定文件以.ts结尾,编写react时,以.tsc为后缀
- 主流的IDE中都支持TS,包括代码补全、接口提示、跳转定义、重构
2.数据类型--任意值--推论
ts原始数据类型
- string number boolean null undefined enum symbol
- 空值一般用void表示
- void可以表示变量,也可表示函数无返回值
ts中的任意值
- 任意值(any)用来表示赋予任意类型
- 声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值
- 变量如果在声明的时候,未制定其类型,那么它会被识别为任意值类型
var num: any = 1;
num = true;
num = "3";
var num2;//没有赋值操作,就会被认为任意值类型,等价于var num2:any;
num2 = 1;
num2 = true;
ts中的类型推论
- typescript会按照类型推论的规则推断出一个类型
var b = 1; //给变量赋值初始值的时候,如果没有指定类型,根据初始值倒推类型
//所以下面赋值“2”是错的,只能赋值为number类型
b = "2";
- 如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成any类型而完全不被类型检查
var b;//没有给b赋初始值,就是any。 相当于var b:any;
b = 2;
b = true;
ts联合类型
- 联合类型表示取值可以为多种类型中的一种
var muchtype:string|number = 3
muchtype = "ee"
-
如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成any类型而完全不被类型检查
-
只能访问此联合类型内的所有类型里的共有的属性或者方法
var muchtype:string|number = "string"
muchtype = 10;
//number类型没有length属性,所以下面的代码会报错
console.log(muchtype.length)
//string和number都有toString方法,所以不会报错
console.log(muchtype.toString())
3.联合类型--接口
ts中对象类型--接口
-
可描述类的一部分抽象行为,也可描述对象的结构形状
-
接口一般字母大写,有的编程语言上面建议接口的名称加上i前缀
-
赋值的时候,变量的形状必须要跟接口的形状保持一致
-
接口中可定义可选属性、只读属性、任意属性
//定义接口
interface Istate {
name : string
}
var obj1: Istate;
//obj1 = {} //接口中的name属性必须要写的
obj1 = {name : "张三" 0}
//可选属性
interface Istate2 {
name : string,
age? : number //存疑,可有可无
}
var obj2 : Istate2;
obj2 = { name : "张三" , age : 20 }
obj2 = { name : "李四"}
//当属性个数不确定的时候 any必须是任意类型
interface Istate3 {
name : string,
age? : number,
[propname : string] : any
}
var obj3:Istate3 = {name : "张三" , age : 10 , sex : "男"}
//只读属性
interface Istate4 {
name : string,
readonly age : number
}
var obj4:Istate4 = { name : "张三" , age : 10};
//obj4.age = 20; //age一旦赋予初始值之后。就不能再对其进行更改了
4.数组类型
- 可采用[类型 + 方括号]表示法
//数组表示法
//类型+方括号
var arr:number [] = [1,2,3]
var arr2:string [] = ["1","2","3"]
var arr3:any [] = [1,"2" , true]
- 可采用数组泛性Array表示法
var arrType: Array<number> = [1 , 2, 3]
var arrType2: Array<string> = ["1" , "2" , "3"]
var arrType3: Array<any> = [1 , "2" , true]
- 可采用接口表示法
interface Istate {
usename : string,
age : number
}
var arrType4:IArr = [1 , 2, 4]
interface Istate {
username : string,
age : number
}
interface IArr {
[inde: number] : Istate
}
var arrType4:IArr = [{username : "张三" , age : 22}]
var arrType5: Array<Istate> = [{username : "张三" , age : 22}]
var arrType6:Istate[] = [{username : "张三" , age : 22}]
5.函数类型
函数约束 有函数本身的参数约束,返回值约束 还有函数本身赋值的变量的约束
//声名式类型的函数
function funcType(name : string , age : number):number {
return age;
}
var ageNum : number = funcType("张三" , 18)
//函数参数不确定
function funcType2(name : string , age : number , sex? :string):number {
return age;
}
var ageNum2:number = funcType2("张三" , 18 , "男")
//函数参数默认值
function funcType3(name : string , age : number=18):number {
return age;
}
//表达式类型的函数
var funcType4 = function(name : string , age:number):number {
return age;
}
//函数变量的约束规范
//第一种方法
var funcType5:(name : string , age:number)=> number = function(name : string , age:number):number {
return age;
}
//第二种方法
interface funcType6 {
(name : string , age : number) : number
}
var funcType6:funcType6 = function(name : string , age:number):number {
return age;
}
可采用重载的方式来支持联合类型的函数关系
//对于联合类型的函数,可以采用重载的方式
//输入是number,输出也是number
//输入是string,输出也是string
function getValue(value : number):number
function getValue(value : string) : string
function getValue(value : string|number):string|number {
return value
}
let a:number|string = getValue(1);
let b:number = getValue(1);
let c:string = getValue("1");
6.类型断言
- 类型断言可以用来手动指定一个值的类型,语法:<类型>值或者值as类型
- 在tsx语法(react的jsx语法的ts版)必须采用后面一种
- 类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的
如果要使用某一种类型的方法或者属性,解决下面的问题
// let num:number|string = "18";
// num = 20;
// console.log(num.length)
解决方法
//类型断言,只能断言联合类型中存在的类型
function getAssert(name:string|number) {
// return (<string>name).length
return (name as string).length
}
7.类型别名
- 类型别名可以用来给一个类型起一个新名字
- 采用关键字type 例如type Name = string | number
- 例子中name就表示可设置字符串和数值类型
- 也可采用type来约束取值只能是某些字符串中的一个,:如
- type EventNames = "click"|"scroll"|"mousemove"
//类型别名
// var str:string|number = "10";
type strType = string|number|boolean;
var str:strType = "10";
str = 10;
str = false;
//可以对于接口也采用类型别名
interface muchType1 {
name : string
}
interface muchType2 {
age : number
}
type muchType = muchType1 | muchType2
var obj : muchType = { name : "张三"}
var obj2: muchType = {age : 10}
var ocj3: muchType = { name : "张三" , age : 10}
//限制字符串的选择
type sex = "男" | "女"
function getSex(s:sex):string {
return s;
}
getSex("男")
8.枚举
- 枚举(Enum)类型用于取值被限定在一定范围内的场景
- 采用关键字enum定义,例如:enum Days{Sun , Mon , Tue , Wed , Thu , Fri,Sat}
- 枚举成员会被赋值为从0开始递增的数字,同时也会被枚举值到枚举名进行反向映射
//使用枚举可以定义一些有名字的数字常量
enum Days {
Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat
}
console.log(Days.Sun) // 0
console.log(Days.Sat) // 6
console.log(Days) //枚举类型会被编译成一个双向映射的对象
console.log(Days[0] === "Sun") //true
如果给予默认值,从给予的默认值开始累加
//使用枚举可以定义一些有名字的数字常量
enum Days {
Sun=3,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat
}
console.log(Days.Sun) // 3
console.log(Days.Sat) // 9
9.修饰类型
public private protected
- public修饰的属性或者方法是共有的,可以在任何地方被访问到,默认所有的属性或者方法都是public上午
- private修饰的属性或者方法是私有的,不能在声明它的类外面访问
- protected修饰的属性或者方法是受保护的,它和private类似
//创建person类
class Person {
name="张三"
age=18
say() {
console.log("我的名字是"+this.name+",我的年龄是" + this.age)
}
}
//创建person实例
var p = new Person();
p.say()
console.log(p.name); //当一个类成员变量没有修饰的时候,外界是可以进行访问的,默认就是public进行修饰
假设name不希望外界访问
private属性只能在类的内部进行访问,在外面无法访问被private修饰的属性或者方法
//创建person类
class Person {
private name="张三"
age=18
say() {
console.log("我的名字是"+this.name+",我的年龄是" + this.age)
}
}
//创建person实例
var p = new Person();
p.say()
//console.log(p.name); 这句话会报错
//private属性只能在类的内部进行访问,在外面无法访问被private修饰的属性或者方法
子类继承了父类,子类就可以访问到父类公开的属性或者方法了
//创建person类
class Person {
private name="张三"
age=18
say() {
console.log("我的名字是"+this.name+",我的年龄是" + this.age)
}
}
//创建child子类
//一旦父类将属性定义成私有之后,子类就不可以进行访问了
class Child extends Person {
callParent(){
super.say()
}
}
var c = new Child();
c.callParent();
console.log(c.age); //子类继承了父类,子类就可以访问到父类公开的属性或者方法了
子类继承了父类,但是没有办法直接获取到父类私有的属性或者受保护的属性
//创建person类
class Person {
private name="张三"
protected age=18
say() {
console.log("我的名字是"+this.name+",我的年龄是" + this.age)
}
}
//创建child子类
//父类的属性定义成受保护的之后,可以在子类里面进行访问
class Child extends Person {
callParent(){
console.log(super.age)
super.say()
}
}
var c = new Child();
c.callParent();
console.log(c.age); //子类继承了父类,但是没有办法直接获取到父类私有的属性或者受保护的属性
类的静态方法里面,是不允许使用this
//创建person类
class Person {
private name="张三"
protected age=18
say() {
console.log("我的名字是"+this.name+",我的年龄是" + this.age)
}
}
//创建child子类
class Child extends Person {
callParent(){
super.say()
}
static test() {
// console.log("this") //会报错
}
}
var c = new Child();
console.log(Child.test()); //类的静态方法里面,是不允许使用this
10.泛型
泛型是指在定义函数、接口或者类的时候,不预先指定具体类型,而在使用的时候再指定类型的一种特性
好处:使得代码更具有健壮性、维护性更高
解决问题:没有确切定义返回值类型,运行的数组每一项可以是任意类型
//没有确切定义返回值类型,运行的数组每一项可以是任意类型
function createArray(length: number , value : any):Array<any> {
let arr = [];
for(var i = 0;i<length ; i++) {
arr[i] = value
}
return arr;
}
createArray(3 , 1)
利用泛型将上述代码进行改造,
泛用来帮助我们限定约束规范
function createArray<T>(length : number , value : T):Array<T> {
let arr = [];
for(var i = 0;i<length ; i++) {
arr[i] = value
}
return arr;
}
//1.传类型
var strArr: string[] = createArray<string>(3 , "1")
//2.不传的时候根据数据类型进行反推
var numArr:number[] = createArray(3 , 1)
接口当中采用泛型
interface ICreate {
<T>(name : string , value : T) : Array<T>
}
let func:ICreate;
func = function<T>(name : string , value :T):Array<T> {
return []
}
var strArr:string [] = func("1" , "2")