typescript笔记
一、安装
npm install -g typescript
tsc -v 检测是否已安装
tsc --init 项目中创建生成tsconfig.json
“outDir”: “./js”, tsconfig.json里配置之后,ts编译的js就会放到./js文件夹里面
终端–>运行任务- ->typescript–>tsc:监听 -》这样配置就可以编辑ts自动编译成js
二、数据类型
-
boolean 、number、string
定义变量必须定义数据类型:let a:number=12
-
array 数组定义方法:
let arr:number[]=[1,2,3]
数组元素只能是数字类型,其他类型以此类推
let arr:Array<number>=[1,2,3]
-
tuole(元组类型、数组中的一种)
let arr:[string,number,boolean]=["12",12.2,true]
-
enum 枚举类型
enum Flag{success=1,error=-1}
let f:Flag=Flag.success
如果没有赋值,则为其索引,f为0
enum Flag{success,error}
let f:Flag=Flag.success
如果部分赋值部分不赋值,不赋值的值则以上一个值的值+1
enum Flag{success,error=5,red}
let f:Flag=Flag.success
0
let f:Flag=Flag.error
5
let f:Flag=Flag.red
6 -
any 任意类型
let num:any=12
let oBox:any=document.getElementById('box')
oBox.style.color='red'
-
null 、undefined 其他(never类型)类型的子类型
let val:undefined=12
let val:number | undefined
let val:number | undefined | null
-
void 表示没有任何类型,一般用于定义方法的时候方法没有返回值
function run():void{ console.log(111111111) }
-
never 其他类型 包含null和undefined,代表从不会出现的值,意味着声明never的变量只能被never类型所赋值
let a:never;
a=(()=>{ throw new Error('错误')})()
三、函数
1、声明函数
- 函数声明法
function run():number{ return 111111111 }
- 匿名函数法
let run=function():number{ return 111111111 }
2、函数传参
- 普通传参
let run=function(num:number,text:string):string{
return `${num}--${text}`
}`
- 可选参数
es5中实参和形参可以不一样,但是ts中必须一样,如果不一样需要配置可选参数
let run=function(num:number,text?:string):string{
return `${num}--${text}`
}`
run(1) //可选参数不传极了一个问号,这样写就不会报错
- 默认参数
es5不能设置默认参数,es6和ts可以设置默认参数
let run=function(num:number,text:string='好'):string{
return `${num}--${text}`
}
run(1)
- 剩余参数
let run=function(...result:number[]):string{
let sum =0
for(let i=0;i<result.length;i++){
sum+=result[i]
}
return sum
}
let run=function(a:number,...result:number[]):string{
let sum =a
for(let i=0;i<result.length;i++){
sum+=result[i]
}
return sum
}
3、函数的重载
Java中方法的重载:指的是两个或两个以上同名函数,但参数不一样,这时会出现函数的重载
typescript中的重载:通过为同一个函数类型定义来实现多种功能的目的
function getInfo(name:string):string;
function getInfo(age:number):number;
function getInfo(str:any):any{
if(typeof str ==='string'){
return '我是'+str
}else{
return '年龄'+str
}
};
四、类
1、定义
》》》》es5
- 对象冒充实现继承
Person(){
this.name:"张三"
}
Person.prototype.sex="男"
function Web (){
Person.call(this)//对象冒充实现继承,可以继承构造函数里面属性方法,没发继承原型链上面属性方法
}
let p =new Web()
console.log(p.name)//张三
console.log(p.sex)//会报错
- 原型链实现继承
既可以继承构造函数里面属性方法,也可以继承原型链上面属性方法
function Person(){
this.name:"张三"
}
Person.prototype.sex="男"
function Web (){
}
Web.prototype=new Person()
let p =new Web()
console.log(p.name)//张三
console.log(p.sex)//男
- 原型链+对象冒充的组合继承模式
function Person(name){
this.name:name
}
Person.prototype.sex="男"
function Web (name){
Person.call(this,name)
}
Web.prototype=new Person()//第一种写法
Web.prototype= Person.prototype//第二种写法
let p =new Web("张三")
console.log(p.name)//张三
console.log(p.sex)//男
》》》》typescript
class Person{
name:string; //属性 前面省略了public关键词
constructor(n:string){ //构造函数 实例化类的时候触发的方法
this.name=n
}
run():void{
console.log(this.name)
}
}
let p =new Person("张三")
p.run()
2、继承 extends 、super
执行子类方法时,会首先匹配子类里的,如果子类没有,再去找父类里的
class Person{
name:string; //属性 前面省略了public关键词
constructor(n:string){ //构造函数 实例化类的时候触发的方法
this.name=n
}
run():void{
console.log(this.name)
}
}
class Web extends Person{
constructor(name:string){
super(name) //初始化父类的构造函数
}
}
3、修饰符
typescript里面定义属性的时候给我们提供了三种修饰符:
public
公有。在类里面、子类、类外面都可以访问
protected
保护类型。在类里面、子类里面可以访问,类外部不能访问
private
私有。在类里面可以访问,子类和类外部不可访问
如果不加修饰符,默认为公有
class Person{
public name:string; //属性 前面省略了public关键词
constructor(n:string){ //构造函数 实例化类的时候触发的方法
this.name=n
}
run():void{
console.log(this.name)
}
}
class Web extends Person{
constructor(name:string){
super(name) //初始化父类的构造函数
}
}
let b=new Web("wan")
b.run()
4、静态方法 static
实例方法是需要先先实例化才能调用,静态方法可直接用
静态方法里面没法直接调用类里面得方法
class Person{
name:string;
static age:number;//静态属性
constructor(n:string){
this.name=n
}
run():void{
console.log(this.name)
}
static pint(){
console.log("静态方法")
}
static getName(){
console.log(this.name,this.age)
}
}
let p=new Person("张三")
p.run()//张三
Person.pint()//静态方法
Person.getName()//Person undefined
- 多态 (也属于继承):父类定义一个方法不去实现,让继承它的子类去实现,每一个子类有不同得表现
class Animal {
name: string;
constructor(n: string) {
this.name = n
}
eat(): void {
console.log("吃")
}
}
class Dog extends Animal {
constructor(name: string) {
super(name)
}
eat(): void {
console.log("吃骨头")
}
}
class Cat extends Animal {
constructor(name: string) {
super(name)
}
eat(): void {
console.log("吃鱼")
}
}
5、抽象类
抽象类:是提供其他类继承得基类,不能直接实例化。用abstract
关键字定义抽象类和抽象方法,抽象类中得抽象方法不包含具体实现并且必须再派生类中实现
adstract抽象方法只能放在抽象类里面
- 抽象类和抽象方法用来定义标准
标准 Animal 这个类要求它的子类必须包含eat方法
abstract class Animal {
public name: string;
constructor(n: string) {
this.name = n
}
abstract eat(): any;//抽点给方法不包含具体实现并且必须在派生类中实现
}
class Dog extends Animal {
// 抽象类的子类必须实现抽象类里面的抽象方法
constructor(name: string) {
super(name)
}
eat(): void {
console.log("吃骨头")
}
}
五、接口 interface
接口的作用,在面向对象编程中,接口是一种规范的定义,它定义了行为和动作的规范,在编程设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里面方法的实现细节,它只规范这批类里面必须提供某些方法,提供这些方法的类就可以满足实际需求。typescript中的接口类似于Java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等
1、属性接口
对参数的约束
function printLabel(info:{label:string}):any{}
printLabel({label:"zhangsan"})
批量方法传入参数进行约束
interface
interface FullName {
fistName: string;//必须;结束
secondName: string;
age?:number;//可选属性
}
function prinName(name: FullName) {
console.log(name)
}
let obj = {
age: 18,
fistName: "张三",
secondName: "里斯"
}
prinName(obj)//这样写可以不要求只含fistName、secondName
prinName({//这样写必须只含fistName、secondName
fistName: "张三",
secondName: "里斯"
})
ts封装ajax(这里只是写个实现效果,没有封装全)
interface Config {
type: string;
url: string;
data?: string;
dataTaye: string;
}
function ajax(config: Config) {
var xhr = new XMLHttpRequest();
xhr.open(config.type, config.url, true);
xhr.send(config.data);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText)
} else {
return "err"
}
}
}
ajax(
{
type: 'get',
url: 'http://a.itying.com/api/productlist',
dataTaye: "json"
}
)
2、函数接口
对方法传入的参数和返回值进行约束
interface Config {
(key: string, value: string): string
}
let p: Config = function (key: string, value: string) {
return key + value
}
console.log(p("key", "value"))//keyvalue
3、可索引接口
对数组、对象的约束
interface UseArr {
[index: number]: number
}
let arr: UseArr = [1]
interface UseObj {
[index: string]: number
}
let obj: UseObj = { age: 1 }
4、类类型接口
对类的约束
interface Animal {
name: string;
eat(str: string): any;
}
class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name
}
eat(): void {
console.log("吃骨头")
}
}
5、接口扩展
接口可以继承接口
interface Animal {
eat(): any;
}
interface Person extends Animal {
name: string;
work(): void;
}
class Web implements Person {
name: string;
constructor(name: string) {
this.name = name
}
eat() { }
work() { }
}
继承类+接口继承接口
interface Animal {
eat(): any;
}
interface Person extends Animal {
name: string;
work(): void;
}
class Per {
name: string;
constructor(name: string) {
this.name = name
}
}
class Web extends Per implements Person {
constructor(name: string) {
super(name)
}
eat() { }
work() { }
}
六、泛型 interface
泛型,软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像c#和Java这样的语言中,可以使用泛型来创建宠用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。
通俗理解,泛型就是解决 类、 接口、 方法的服用,以及对不特定数据类型的支持
- 定义、函数
T可以自己定义,表示泛型,具体什么类型是是调用这个方法的时候决定的
function getData<T>(value: T): T {
return value
}
getData<number>(1)
getData<string>("黑哈哈")
- 类
class Last<T>{
public list: T[] = [];
add(value: T): void {
this.list.push(value)
}
last(): T {
return this.list[this.list.length - 1]
}
}
let p = new Last<number>()
p.add(12)
p.add(13)
console.log(p.last())
- 接口
interface Config {
<T>(value: T): T
}
function getData<T>(value: T): T {
return value
}
getData<number>(12)
- 把类作为参数类型的泛型类
把类作为参数约束数据传入的类型
class User {
name: string | undefined;
age: number | undefined;
}
class List {
add(user: User): boolean {
console.log(user)
return true
}
}
let p = new User()
p.name = "张三"
let u = new List()
u.add(p)
class User {
name: string | undefined;
age: number | undefined;
}
class List<T> {
add(user: T): boolean {
console.log(user)
return true
}
}
let p = new User()
let b = new List<User>()
p.name = "qw"
b.add(p)
七、命名空间 namespace
组织代码,避免命名冲突
一个文件里面可以有多个命名空间
命名空间里面的属性方法默认私有的,需要export暴露
namespace A {
export class User {
name: string | undefined;
age: number | undefined;
}
export class List {
add(user: User): boolean {
console.log(user);
return true;
}
}
}
let p = new A.List();
八、装饰器
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上,可以修改类的行为。
常见的装饰器:类装饰器、属性装饰器、方法装饰器、参数装饰器
装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参)
1、类装饰器
- 普通装饰器
function logClass(params: any) {
// params 就是当前类
console.log(params);
params.prototype.apiUrl = "xxx"; //动态扩展的属性
}
@logClass //不能加分号;
class HttpClient {
constructor() {}
getData() {}
}
let http = new HttpClient();
console.log(http);
- 装饰器工厂
function logClass(params: string) {
return function (target: any) {
console.log(params);
console.log(target);
target.prototype.apiUrl = params;
};
}
@logClass("api")
class HttpClient {
constructor() {}
getData() {}
}
let http: any = new HttpClient();
console.log(http.apiUrl);
类装饰器表达式会在运行时当做函数被调用,类的构造函数作为其唯一的参数。
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
- 类修饰器来重载类的构造函数
function logClass(params: any) {
return class extends params{
apiUrl:any = "params";
getData(){
console.log(this.apiUrl)
}
};
}
@logClass
class HttpClient {
public apiUrl:string |undefined;
constructor() {
this.apiUrl="内部"
}
getData() {
console.log(this.apiUrl)
}
}
let http: any = new HttpClient();
http.getData()//params
2、属性装饰器
属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
1、原型对象。对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、当前属性的名称。成员的名字。
function logClass(params: any) {
return function (target: any, attr: any) {
console.log(target)
console.log(attr)
target[attr] = params
};
}
class HttpClient {
@logClass("123")
public apiUrl: string | undefined;
@logClass("7777777777")
public apiUrl1: string | undefined;
constructor() {
}
getData() {
console.log(this.apiUrl)
console.log(this.apiUrl1)
}
}
let http: any = new HttpClient();
http.getData()//123 7777777777
3、方法装饰器
会被应用大方法的属性描述符上,可以用来监视、修改或者替换方法定义
方法装饰器在运行时传入3个参数:
1、原型对象。对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、属性名称
3、属性描述符
function logClass(params: any) {
return function (target: any, name: any, desc: any) {
target.url = "xxx"//给HttpClient扩展属性
target.add = function () {//给HttpClient扩展方法
console.log(params)
}
// 修改修饰器的方法
let oMethod = desc.value
desc.value = function (...arr: any[]) {
arr = arr.map((value) => {
return value + "--"
})
oMethod.apply(this, arr)//如果不写这一句 则就变成替换方法了
}
};
}
class HttpClient {
public apiUrl: string | undefined;
constructor() {
}
@logClass("123")
getData(v: any) {
console.log(v)
}
}
let http: any = new HttpClient();
http.add()//123
console.log(http.url)//xxx
http.getData(1)//1--
4、参数装饰器
参数装饰器表达式会在运行时当作函数被调用,可以使用参数装饰器为类的原型增加一些元素数据,传入3个参数:
1、原型对象。对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
2、方法名称
3、参数在函数参数列表中的索引
function logClass(params: any) {
return function (target: any, name: any, index: any) {
target[name](params)//123
target.apiUrl = params
};
}
class HttpClient {
public apiUrl: string | undefined;
constructor() {
}
getData(@logClass("123") v: any) {
console.log(v + this.apiUrl)
}
}
let http: any = new HttpClient();
http.getData(1)//1123
- 执行顺序
function logClass(params: any) {
return function (target: any) {
console.log("类1")
};
}
function logClass2(params: any) {
return function (target: any) {
console.log("类2")
};
}
function logAttr(params: any) {
return function (target: any, attr: any) {
console.log("属性1")
};
}
function logAttr1(params: any) {
return function (target: any, attr: any) {
console.log("属性2")
};
}
function logM(params: any) {
return function (target: any, attr: any) {
console.log("方法1")
};
} function logM1(params: any) {
return function (target: any, attr: any) {
console.log("方法2")
};
}
function logC(params: any) {
return function (target: any, attr: any, index: any) {
console.log("参数1")
};
}
function logC1(params: any) {
return function (target: any, attr: any, index: any) {
console.log("参数2")
};
}
@logClass(12)
@logClass2(12)
class HttpClient {
@logAttr(12)
public apiUrl: string | undefined;
@logAttr1(12)
public apiUrl1: string | undefined;
constructor() {
}
@logM(12)
getData(@logC("123") v: any, @logC1("123") v1: any) {
console.log(this.apiUrl)
}
@logM1(12)
getData1(@logC("123") v: any, @logC1("123") v1: any) {
console.log(this.apiUrl)
}
}
let http: any = new HttpClient();
http.getData(1)
// 属性1 属性2 参数2 参数1 方法1 参数2 参数1 方法2 类2 类1 undefined