TypeScript-基础教程
Posted JackieDYH
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript-基础教程相关的知识,希望对你有一定的参考价值。
一、什么是TypeScript
它是拥有类型系统的javascript的超集,可以编译成纯JavaScript
特点:
类型检查:TS在编译代码时进行严格的静态类型检查
语言扩展:TS会包括来自ES6和未来提案中的特性。比如异步操作和装饰器也会从其他语言中借鉴特性例如接口和抽象类
工具熟悉:TS可以编译成标准的JavaScript可以在任何浏览器和操作系统上运行
从以上特性上来看TS更像是一个工具而不是一门独立的语言
二、TS的安装及使用
cnpm install typescript -S
npx tsc --init
创建tsconfig.json文件
三、数据类型
JS基本数据类型
Boolean
Number
String
Undefined
Null
Array
Function
Object
Symbol
TS数据类型
包含以上9个
void
any
never
元组
枚举
高级类型
1、类型注解
作用:相当于强类型语言中的类型声明
语法:变量/函数:type
基本类型
let bool:boolean = true;
let str:string = "Alley";
let num:number = 18;
数组类型
//数组
let arr1:number[] = [1,2,3,4];
let arr2:Array<number> = [1,2,3,4];
元组类型
元组类型:限定数组的中类型和个数,上述案例中只能有2个数据并且必须是一个数组一个字符串元组类型可以通过push进行添加但是不能访问
//元组
let tuple:[number,string] = [0,'Alley']
对象类型
let obj:x:number = x:1
//定义obj是一个对象并且x值为number
symbol类型
let s1:symbol = Symbol();
undefind null类型
let un:undefined = undefined;
let nu:null = null;
联合类型
联合类型(Union Types)表示取值可以为多种类型中的一种,联合类型使用
|
分隔每个类型
let arr2:Array<number | string> = [1,"Alley"];
//数组中的类型可以是数字也可以是字符串
函数类型
let fn = (x:number,y:number):number=>x+y;
//参数x:为数字 y:为数字 返回值也必须是数字
void类型
JavaScript 没有空值(Void)的概念,在 TypeScript 中,可以用
void
表示没有任何返回值的函数:
let fn = ()=>
//代表函数的返回值为空
any类型
任意值(Any)用来表示允许赋值为任意类型
如果是一个普通类型,在赋值过程中改变类型是不被允许的,但如果是
any
类型,则允许被赋值为任意类型
let x:any;
//any为任意类型
never类型
永远都不会有返回值
let error = ()=>
throw new Error("error")
2、枚举类型
什么是枚举类型:一组有名字的常量集合。可以理解成手机的通信录Alley=>18399776655
枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。
枚举使用
enum
关键字来定义枚举成员会被赋值为从
0
开始递增的数字,同时也会对枚举值到枚举名进行反向映射枚举类型的优点:
可维护性
可读性
数字枚举
enum Status
success,
error,
wraning
//数字枚举默认从0开始也就是说Status.success为0 Status.error为1
//同时我们还可以设置初始值,后面的枚举成员依次递增
enum Status
success=10,
error,
wraning
3、接口
接口的作用 : 可以用来约束对象、函数、类的结构
关键字:interface
在 TypeScript 中,我们使用接口(Interfaces)来定义对象的类型。
接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement)。
TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。
接口一般首字母大写
interface List
id:number;
name:string;
interface Result
data:List[];
function success(result:Result)
let result =
data:[
id:1,name:"Alley",
id:2,name:"彦祖"
]
/*
上述案例中定义了一个List接口,接口中必须存在id和name并且id为number,name为string
同时也定义了一个Result接口,接口中规定key为data value为List接口类型并且是一个数组
还原以上接口的数据为result
*/
定义的变量比接口少了一些属性是不允许的
inteface Person
name:string,
age:number
//会报错 少了age
let man:Person=
name:"alley"
多一些属性也是不允许的
inteface Person
name:string,
age:number
//会报错 少了age
let man:Person=
name:"alley",
age:19,
sex:"男"
可见,赋值的时候,变量的形状必须和接口的形状保持一致
可选属性
有时我们希望不要完全匹配一个形状,那么可以用可选属性,可选属性的含义是该属性可以不存在 可选属性用
?
来定义
inteface Person
name:string,
age?:number
let man:Person=
name:"alley"
只读属性
有时候我们希望对象中的一些字段只能在创建的时候被赋值,那么可以用
readonly
定义只读属性
inteface Person
readonly name:string,
age?:number
let man:Person=
name:"alley"
man.name="吴彦祖"//报错
4、数组类型
在 TypeScript 中,数组类型有多种定义方式,比较灵活
「类型 + 方括号」表示法
let arr:number[] =[1,2,3,4,5]
let arr:number[] =[1,2,3,'4',5]; //报错
数组泛型
也可以使用数组泛型(Array Generic)
Array<elemType>
来表示数组:
let arr=Array<number>=[1,2,3,4,5]
用接口表示数组
interface NumArray
[index:number]:number
let arr:NumArray=[1,2,3,4]
NumArray
表示:index
的类型是number
,值的类型是number
。
5、函数类型
定义函数的方式
let add:(x:number,y:number)=>number;
interface Add
(x:number,y:number):number
//实现函数
let add:Add = (x,y)=>x+y;
可选参数
与接口中的可选属性类似,我们用
?
表示可选的参数注意:
可选参数必须接在必需参数后面
function fn(name:string,age?:number)
return name+age;
参数默认值
TypeScript 会将添加了默认值的参数识别为可选参数
function fn(name:string='alley',age?:number)
return name+age;
剩余参数
ES6 中,可以使用
...rest
的方式获取函数中的剩余参数
function fn(name:string,....rest:any[])
函数重载
如果函数名称相同,但是参数类型不同或者参数个数不同,就需要实现了函数重载
好处:不需要为功能相似的函数起不同的名称
ts实现函数重载:要求定义一系列的函数声明,在类型最宽泛的版本中实现重载
function fn(...rest:number[]):number;
function fn(...rest:string[]):string;
function fn(...rest:any[])
let first = rest[0];
if(typeof first == "number")
//return
if(typeof first == "string")
//return
6、类
使用
class
定义类,使用constructor
定义构造函数。通过
new
生成新实例的时候,会自动调用构造函数。使用
extends
关键字实现继承,子类中使用super
关键字来调用父类的构造函数和方法。
存储器
使用 getter 和 setter 可以改变属性的赋值和读取行为:
class Animal
constructor(name)
this.name=name;
get name()
return'alley';
set name(value)
console.log('name: '+value);
let a= new Animal('alley'); // name: alley
a.name='alley'; // name: alley
console.log(a.name); // alley
静态方法
使用
static
修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用
class Person
static show()
Person.show()
ES7中类的使用
ES6 中实例的属性只能通过构造函数中的
this.xxx
来定义,ES7 提案中可以直接在类里面定义ES7 提案中,可以使用
static
定义一个静态属性:
class Person
name="alley"
static age=19;
public private 和 protected
public
修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是public
的
private
修饰的属性或方法是私有的,不能在声明它的类的外部访问
protected
修饰的属性或方法是受保护的,它和private
类似,区别是它在子类中也是允许被访问的
class Animal
public name;
public constructor(name)
this.name=name;
let a=new Animal('Jack');
console.log(a.name); // Jack
a.name='Tom';
console.log(a.name); // Tom
class Animal
private name;
public constructor(name)
this.name=name;
let a=new Animal('Jack');
console.log(a.name); // 会出问题
class Animal
private name;
public constructor(name)
this.name=name;
class Cat extends Animal
constructor(name)
super(name);
console.log(this.name);//会出问题
如果是用
protected
修饰,则允许在子类中访问
class Animal
protected name;
public constructor(name)
this.name=name;
class Cat extends Animal
constructor(name)
super(name);
console.log(this.name);
抽象类
抽象类 只可以被继承,不可以被实例化
通过关键字
abstract
进行定义
abstract class Person
let p = new Person();//会报错
7、类与接口
一个接口可以约束类成员有哪些属性以及他们的类型
注意:类实现接口的时候必须实现接口中所有声明的属性
接口只能约束类的公有成员(public)
interface Info
name:string
eat()
class Person implements Info
constructor(name:string)
this.name = name;
eat()
接口继承接口
接口与接口之间可以是继承关系
interface Alarm
alert();
interface LightableAlarm extends Alarm
lightOn();
lightOff();
一个类可以实现多个接口
interface Alarm
alert();
interface Light
lightOn();
lightOff();
class Car implements Alarm, Light
alert()
console.log('Car alert');
lightOn()
console.log('Car light on');
lightOff()
console.log('Car light off');
8、泛型函数和泛型接口
什么是泛型?
不预先确定的数据类型,具体的类型在使用的时候才能被确定
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
泛型函数
function fn<T>(value:T):T
console.log(value);
return value;
//T类似于any类型,可以保证函数的输入和输出是一致的
//调用
fn<string>("Alley");//在调用的时候来定义类型
泛型接口
interface SearchFunc
//函数返回值是一个布尔值
(source: string, subString: string): boolean;
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string)
return source.search(subString) !==-1;
泛型类
通过泛型对类进行约束,在实例化的时候来定义这个T的类型那么这个类内部的T都必须是这个类型
class Person<T>
show(value:T)
console.log(value);
return value;
let p = new Person<number>()
p.show(1)
泛型约束
在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法:
function fn<T>(value:T):T
console.log(value.length);
//这里会出问题,原因是并不是所有的参数都有length属性
return value;
我们可以对泛型进行约束,只允许这个函数传入那些包含
length
属性的变量。这就是泛型约束:
interface Len
length:number
function fn<T extends Len>(value:T):T
console.log(value.length);
return value;
上例中,我们使用了
extends
约束了泛型T
必须符合接口Len
的形状,也就是必须包含length
属性。此时如果调用
fn
的时候,传入的value
不包含length
,那么在编译阶段就会报错
以上是关于TypeScript-基础教程的主要内容,如果未能解决你的问题,请参考以下文章