TyptScript基础语法
ts官网地址:https://www.tslang.cn/docs/handbook/typescript-in-5-minutes.html
ts安装
npm install -g typescript
- 查看ts安装版本
tsc -v
编译ts
- 将ts编译为es5代码(需要每次手动编译)
tsc hellworld.ts
- 创建ts.config.json文件,修改outDir,自动编译.ts文件
- 终端-》运行任务-》tsc:监视
tsc --init
- 全局安装ts-node进行ts编译
npm install -g ts-node
ts基本语法
ts中的数据类型
- 一个元素可以设置多个类型
布尔类型(boolean)
let bool:boolean=true
数字类型(number)
let num:number=100
字符串类型(string)
let str:string='hell'
数组类型(array)
let ary1:number[]=[]
let ary2:Array<number>=[12]
元组类型(tuple)
元组类型属于数组的一种
let ary3:[string,number,boolean]=['hell',19,true]
枚举类型(enum)
事先考虑到某一变量可能取到的值,尽量用自然语言中含义清楚的单词来表示它的每一个值,这种方法称为枚举方法,用这种方法定义的类型称为枚举类型
enum falg{
success=1,
error=0,
blue,
red
}
let f:falg=falg.error;
let f1:falg=falg.blue;
let f2:falg=falg.red;
注意:如果枚举项不赋值,默认是其索引值,并且会跟随前一个值加1,例如f->0,f1->1,f2->2
任意类型(any)
let obj1:any={}
obj1=[]
null 和 undefined
是其他类型)的子类型
let sds:null|number=null
let sds1:undefined=undefined
void类型
void表示没有任何类型,一般用于定义函数
function add(a:number,b:number):void{
let result:number=a+b
}
add(1,3)
never类型
从不会出现的类型,其他类型
let color:string|never
color='red'
函数详解
ts中函数参数和返回值必须设置类型,并且形参和实参类型和个数需要对应,形参可以配置可选参数
- 没有返回值
function add ():void{
console.log('add 函数没有返回值!');
}
add()
- 设置返回值类型
function add (a:number,b:number):number{
return a+b
}
add(1,2)
- 配置可选参数
可选参数一定要放到最后
function add (a:number,b?:number):number{
let result=a+b
return result
}
console.log(add(12,23));
- 默认参数
function add (a:number,b:number=20):number{
return a+b
}
console.log(add(1));
- 剩余运算符接收形参
function add (a:number,b:number,...arg:number[]):number{
let result=a+b+eval(arg.join('+'))
return result
}
console.log(add(12,23,56,65));
函数的重载
java中方法的重载:重载指的是两个或者两个以上同名函数,但是他们的参数不一样,这时会出现函数重载的情况 ts中方法的重载:通过为同一个函数提供多个函数类型定义来实现多种功能的目的
function add (a:number):number;
function add (a:string):string;
function add (a:any):any{
if(typeof a ==='string'){
return `${a}:是一个字符串!`
}
if(typeof a ==='number'){
return `${a}:是一个数字!`
}
}
ts中的类
es5中的构造函数
function person(name,age){
// 定义实例私有属性
this.name=name
this.age=age
// 定义实例私有的方法
this.run=function(){
console.log(`${name}今年${age}岁,依然健步如飞!`);
}
}
// 原型上公共的属性和方法
person.prototype.sex='男'
person.prototype.run2=function(){
console.log('原型上的公共方法');
}
// 定义构造函数的静态属性(此时将构造函数看为是一个对象)
person.name1='静态属性name'
// 定义静态方法
person.run1=function(){
console.log('静态方法');
}
let personObj=new person('小明',99)
console.log(personObj.name,personObj.age,personObj.run(),person.name1,person.run1());
es6中的类
class Person{
constructor(name,age){
this.name=name
this.age=age
}
run(){
console.log(`${this.name}今年${this.age}岁,依然健步如飞!`);
}
static name='静态属性name'
static run=()=>{
console.log('静态方法');
}
}
let personObj=new Person('小明',99)
console.log(personObj.name,personObj.age,personObj.run(),Person.name,Person.run());
ts中的类
ts里面定义属性的时候提供了三个修饰符
- public: 共有的
在类里面、子类、类外面都可以访问(定义时不写默认时public类型)
- protected:保护类型
在类里面、子类里面可以访问
- private: 私有
只在类里面可以访问 在类的静态方法里面无法直接调用类里面的属性
class Person{
name:string;
public age:number;
protected sex:string
private num:number
constructor(name:string,age:number,sex:string,num:number){
this.name=name
this.age=age
this.sex=sex
this.num=num
}
run(){
console.log(`${this.name}今年${this.age}岁,性别${this.sex},有${this.num}根头发`);
}
}
let personObj=new Person('小明',22,'男',666)
console.log(personObj.name,personObj.age,personObj.run());
类的多态
父类定义一个方法不去实现,让继承的子类去实现 多态属于继承,在子类中重写父类中的方法
class Person{
public name:string
protected age:number
constructor(name:string,age:number){
this.name=name
this.age=age
}
run(){}
}
class XiaoMing extends Person{
name:string
age:number
constructor(name:string,age:number){
super(name,age)
this.name=name
this.age=age
}
run(){
console.log(`${this.name},${this.age}岁`);
}
}
let xiao=new XiaoMing('小明',33)
ts中的抽象类
抽象类时提供其他类继承的基类,不能直接被实例化 抽象类就是定义标准的
- abstract抽象方法只能放到抽象类中
- 用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现,并且必须在派生类中实现
abstract class Person{
public name:string
protected age:number
constructor(name:string,age:number){
this.name=name
this.age=age
}
abstract run():any
}
class XiaoMing extends Person{
constructor(name:string,age:number){
super(name,age)
}
run():any{
console.log(`${this.name},${this.age}岁`);
}
}
let xiao=new XiaoMing('小明',33)
ts中的接口
作用:接口是一种规范的定义,ts增加了接口类型,包括属性、函数、可索引和类
属性接口
接口中定义多少项,就要参入多少项,即使多穿,在具体中的函数也不能使用
interface FullName{
// 没项之间使用;结束
name:string;
age:number;
}
function person(obj:FullName){
console.log(`${obj.name}今年${obj.age}岁`);
}
person({name:'小明',age:23})
- 接口中可选属性
interface FullName{
// 没项之间使用;结束
name:string;
age?:number;
}
function person(obj:FullName){
console.log(`${obj.name}`);
}
person({name:'小明'})
函数类型接口
对方法传入的参数、返回值进行约束
interface person{
(key:string,val:number):string;
}
let result:person= function add(key:string,val:number):string{
return key+val
}
console.log(result('xiaomign',56));
可索引接口(不常用)
对数组、对象的约束
interface ary{
[index:number]:string
}
interface obj{
[index:string]:string
}
let ary:ary=["56","23"]
let obj:obj={'name':'xiaomimg',age:'12'}
console.log(ary,obj);
类类型接口
和抽象类相似
interface Animal{
name:string;
eat(str:string):void
}
class Dog implements Animal{
name:string
constructor(name:string){
this.name=name
}
eat(str:string):void{
console.log(`${this.name}开饭了!`);
}
}
接口的拓展
接口继承接口
interface Dog{
run():void
}
interface Animal extends Dog {
name:string;
eat(str:string):void
}
class aaa implements Animal{
name:string
constructor(name:string){
this.name=name
}
eat(str:string):void{
console.log(`${this.name}开饭了!`);
}
run(){
console.log('接口Animal继承了接口Dog');
}
}
泛型
为了考虑可重用性,组件不仅要能够支持当前的数据类型,同时也能够支持未来的数据类型。 泛型就是解决类、接口、方法的复用性,以及对不特定数据类型的支持
- 泛型的函数具体是什么类型,是调用的时候决定的
泛型函数
function add<T>(num:T):T{
// T就表示类型,只要是大写字母就行,一般用T表示
return num
}
add<number>(56)
function add<T>(num:T):any{
// T就表示类型,只要是大写字母就行,一般用T表示
return num+'使用泛型返回值和参数类型也是可以单独定义的'
}
add<number>(56)
泛型类
class Add<T>{
public list:T[]=[]
add(num:T):void{
this.list.push(num)
}
print():T[]{
return this.list
}
}
let obj=new Add<string>()
obj.add('xiaoming')
obj.print()
console.log(obj.list);
泛型接口
- 方式一
interface config{
<T>(val:T):T
}
let value=function<T>(val:T):T{
return val
}
value<number>(56)
- 方式二
interface config<T>{
(val:T):T
}
let value:config<number>=function<T>(val:T):T{
return val
}
value(56)
ts中的命名空间
- 命名空间:内部模块,主要用于组织代码,避免命名冲突
- 模块: ts的外部模块的简称,侧重代码的复用,一个模块中可以有多个命名空间
可以把命名空间封装为一个模块(就是写在单独一个文件中),可以使用es6导入导出
// 这是命名空间A
namespace A{
export class Name{
// 一个Name类
}
}
// 使用
let dog=new A.Name()
装饰器
装饰器是一种特殊类型声明,它能被附加到类声明、方法、属性或参数上,可以修改类的行为。 通俗的讲装饰器就是一个方法,可以注入到方法、属性参数、类上来扩展类、属性、方法、参数的功能。
- 常见的装饰器有:
- 类装饰器
- 属性装饰器
- 方法装饰器、
- 参数装饰器
- 装饰器的写法:
- 普通装饰器(无法传参)
- 装饰器工厂(可传参)
- 装饰器是过去几年中js最大的成就之一,已是es7的标准特性之一
类装饰器
类装饰器在类声明之前被声明(紧靠着类声明)。类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。传入一个参数
- 普通装饰器
function animolDecorator(params:any){
// params:默认就会传进来,就是Animol这个类
params.prototype.sex='男'
params.prototype.run=function(){
console.log(`${params.prototype.name}在奔跑!`);
}
params.age=1
};
@animolDecorator
class Animol{
name:string
constructor(name:string){
this.name=name
}
}
let dog = new Animol('dog')
- 装饰器工厂
function animolDecorator(value:string){
console.log(`${value}就是传进来的参数`);
return function (params:any){
// params:默认就会传进来,就是Animol这个类
params.prototype.sex='男'
params.prototype.run=function(){
console.log(`${params.prototype.name}在奔跑!`);
}
params.age=1
}
};
@animolDecorator('装饰器工厂')
class Animol{
name:string
constructor(name:string){
this.name=name
}
}
let dog = new Animol('dog')
类装饰器重构当前类
- 类装饰器表达式会在运行时当作函数执行,类的构造函数作为其唯一的参数
- 如果类装饰器返回一个值,他会使用提供的构造函数替换类的声明