一篇文章,讀懂TypeScript

本文轉載自:https://silencesy.github.io/2019/04/29/TypeScript/TypeScript/

一、準備


1. 安裝

npm install -g typescript

2. vscode自動編譯

  • 項目目錄終端執行 tsc --init
  • 更改tsconfig.json “outDir”: “./js”

二、基礎語法


1.數據類型

  • 布爾值
  • 數字
  • 字符串
  • 數組
  • 元組 Tuple
  • 枚舉
  • Any
  • Void (函數沒有返回值使用。)
  • Null 和 Undefined (默認情況下null和undefined是所有類型的子類型。)
  • Never (never類型是任何類型的子類型)
  • Object

2.函數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
聲明函數
function run():string {
    return 'typescript';
}
匿名函數
var fun = function():string {
    return 'typescript';
}
定義方法傳參
function user(name:string,age:number):string {
    return `${name}----${age}`;
}
var user = function(name:string,age:number):string {
    return `${name}----${age}`;
}
沒有返回值
function run():void {
    console.log('typescript'  );
}
方法可選參數
function user(name: string,age?:number):string {
    return `${name}----${age}`;
}
方法參數默認值
function user(name: string,age:number=20):string {
    return `${name}----${age}`;
}
方法剩餘參數
function user(...result:number[]):string {
    
}
function user(name: string,...result:number[]):string {
    
}
重載
function user(name: string):string;
function user(age: number):number;
function user(str:any):any {
    if(typeof str==='string) {
        return str
    } else {
        return str
    }
}

3.類

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
基本模型
class Person {
    name: string; //屬性 省略publick 關鍵詞
    constructor(name:string) {  //構造函數 實例化的時候調用的方法(初始化對象)
        this.name = name;
    }
    run():void {
        alert(this.name);
    }
}

class Person {
    name: string; //屬性 省略publick 關鍵詞
    constructor(name:string) {  //構造函數 實例化的時候調用的方法(初始化對象)
        this.name = name;
    }
    setName():void {
        this.name = name;
    }
    getName():string {
        alert(this.name);
    }
}
var person1 = new Person('張三');
alert(person1.getName());
person1.setName('李四');
alert(person1.getName());

4.繼承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Person {
    name: string; //屬性 省略publick 關鍵詞
    constructor(name:string) {  //構造函數 實例化的時候調用的方法(初始化對象)
        this.name = name;
    }
    run():string {
        return `${this.name}`
    }
}

子類可以使用父類的屬性和方法  如果子類的方法或者屬性和父類相同  則以子類爲主
class Web extends Person {
    constructor(name:string) {
        super(name); //初始化父類的構造函數
    }
    work():string {
        return `${this.name}在運動`
    }
    run():string {
        return `${this.name}` 
    }
}
var w = new Web('李四');
alert(w.run());

5.類裏面的修飾符

  • public

共有類型 在類裏面、子類、類外面都可以訪問(默認,不寫默認就是)。

  • protected

保護類型 在類裏面、子類可以訪問,類外面都不可以訪問。

  • private

私有類型 在類裏面可以訪問,子類和類外面都不可以訪問。

6.類的靜態屬性和靜態方法

  • static (靜態方法裏面不能直接調用類裏面的屬性,能調用靜態屬性)
1
2
3
4
5
6
7
8
9
10
11
12
13
class Person {
    public name:string;
    static age:number=20;
    constructor(name) {
        this.name = name;
    }
    run() {
        alert(`${this.name}在運動`);
    }
    static print() {
        alert(`print`+Person.age); 
    }
}

7.多態

  • 父類定義一個方法不去實現,讓繼承它的子類去實現,讓每一個子類有不同的表現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Animal {
    name:string;
    constructor(name:string){
        this.name = name;
    }
    eat() {
        console.log('喫的方法');
    }
}
class Dog extends Animal {
    constructor(name:string) {
        super(name)
    }
    eat() {
        return this.name + '骨頭'
    }
}
class Cat extends Animal {
    constructor(name:string) {
        super(name)
    }
    eat() {
        return this.name + '魚'
    }
}

8.抽象類

  • 提供標準
  • abstract 抽象類不能實例化 爲子類提供基類
  • 子類必須實現父類的抽象方法
  • abstract必須放在抽象類裏面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class Animal {
    name:string;
    constructor(name:string){
        this.name = name;
    }
    abstract eat():any;
}
class Dog extends Animal {
    constructor(name:any) {
        super(name);
    }
    eat() {
        console.log(this.name);
    }
}

8.接口

  • 定義規範 定義行爲和動作的規範 (接口不關心類內部的數據狀態和方法實現的細節)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
interface FullName {
    firstName: string;
    secondName: string;
}
function printName(name: FullName) {
    console.log(name.firstName+ '--' +name.secondName)
}
var obj = {
    firstName: 'sun',
    secondName: 'yu'
}
printName(obj) // ok


接口的可選屬性
interface FullName {
    firstName: string;
    secondName?: string;
}
function printName(name: FullName) {
    console.log(name.firstName+ '--' +name.secondName)
}
var obj = {
    firstName: 'sun',
    secondName: 'yu'
}
printName(obj) // ok
var obj = {
    firstName: 'sun'
}
printName(obj) // ok

函數類型的接口
interface encrypt {
    (key:string,value:string):string;
}
var md5:encrypt = function(key:string,value:string):string {
    return key+value;
}
md5('key','value');

可索引接口 數組和對象的約束(不常用)
interface userArr {
    [index:number]:string
}
var arr:userArr = ['string','string']; //ok

interface userObj {
    [index:string]:string
}
var arr:userObj = ['string','string']; //ok

類類型接口 對類的約束
interface Animal {
    name:string;
    eat(str:string):void;
}
class Dog implements Animal {
    name: string;
    constructor(name:string) {
        this.name = name;
    }
    eat() {
        return `喫骨頭`;
    }
}
var dog = new Dog('小黑');
dog.eat();


接口擴展  接口擴展接口
interface Animal {
    eat():void;
}
interface Person extends Animal {
    work():void;
}
class Web implements Person {
    public name:string;
    constructor(name:string){
        this.name= name;
    }
    eat() {
        console.log(this.name+'喜歡喫饅頭');
    }
    work() {
        console.log(this.name+'愛工作');
    }
}

---------------------------

interface Animal {
    eat():void;
}
interface Person extends Animal {
    work():void;
}
class programmer {
    public: name:string;
    constructor(name:string) {
        this.name = name;
    }
    coding(code:string){
        console.log(this.name+code);
    }
}
class Web extends programmer implements Person {
    constructor(name:string){
        super(name)
    }
    eat() {
        console.log(this.name+'喜歡喫饅頭');
    }
    work() {
        console.log(this.name+'愛工作');
    }
}

9.泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
function getData<T>(value:T):T {
    return value;
}
getData<number>(123);

function getData<T>(value:T):any {
    return value;
}
getData<number>(123);
getData<string>('123');

泛型類
class MinClass<T> {
    public list:T[]=[];
    add(value:T):void {
        this.list.push(value);
    }
    min():T{
        var minNum = this.list[0];
        for(var i=0;i<this.list.length;i++) {
            if(minNum>this.list[i]) {
                minNum = this.list[i];
            }
        }
        return minNum;
    }
}

var m1 = new MinClass<number>();  // 實例化類 並且制定類的T代表類型是number
m1.add(123);
var m2 = new MinClass<string>();  // 實例化類 並且制定類的T代表類型是string
m2.add('123');

泛型接口
interface ConfigFn {
    <T>(value:T):T;
}
var getData:ConfigFn = function<T>(value: T):T {
    return value;
}
getData<string>('張三');
getData<number>(123);

interface ConfigFn<T> {
    <T>(value:T):T;
}
function getData<T>(value: T):T {
    return value;
}

var myGetData:ConfigFn<string>=getData;
myGetData('張三');
var myGetDataw:ConfigFn<number>=getData;
myGetData(123);


把類作爲參數來約束數據傳入類型
class User {
    userName: string | undefined;
    password: string | undefined;
}
class MysqlDb {
    add(User:User):boolean {
        console.log(User);
        return true;
    }
}
var user = new User();
user.userName = '張三';
user.password = '123456';
var db = new MysqlDb();
db.add(user);
 
泛型類
class User {
    userName: string | undefined;
    password: string | undefined;
}
class MysqlDb {
    add(User:T):boolean {
        console.log(User);
        return true;
    }
}
var user = new User();
user.userName = '張三';
user.password = '123456';
var db = new MysqlDb<User>();
db.add(user);


約束規範使用接口,代碼重用使用泛型。

interface DBI<T> {
    add(info:T):boolean;
    update(info:T,id:number):boolean;
    delete(id:number):boolean;
    get(id:number):any[];
}
class MysqlDb<T> implements DBI<T> {
    add(info:T):boolean {
        console.log(info);
        return true;
    }
    update(info:T,id:number):boolean {
        console.log(info,id);
        return true;
    }
    delete(id:number):boolean {
        console.log(id);
        return true;
    }
    get(id:number):boolean {
        console.log(id);
        return true;
    }
}
class Mongodb<T> implements DBI<T> {
    add(info:T):boolean {
        console.log(info);
        return true;
    }
    update(info:T,id:number):boolean {
        console.log(info,id);
        return true;
    }
    delete(id:number):boolean {
        console.log(id);
        return true;
    }
    get(id:number):boolean {
        console.log(id);
        return true;
    }
}

10.模塊

  • 模塊的概念(官方): ”內部模塊“=》”命名空間“,”外部模塊“=》”模塊“ 模塊在其自身的作用域裏面執行,而不是在全局作用域執行。這就意味着定義一個模塊裏的變量,函數,類等等在模塊外部是不可見的,除非你明確的使用export形式之一導出他們。相反,如果想使用其他模塊導出的變量,函數,類,接口等的時候,你必須要導入它們,可以使用import形式之一。
  • 模塊的概念(自己理解): 我們可以把一些公共的功能單獨抽離成一個文件作爲一個模塊。模塊裏面的變量,函數,類等都是私有的,如果我們要在外部訪問模塊裏面的數據(變量,函數,類),我們需要通過export暴露模塊裏面的數據(變量、函數、類、、、)暴露後我們通過import引用模塊裏面的數據(變量,函數,類)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
定義 db.ts
var a:string = "string";
function getData(value:string):string {
    return value
}
export {
    a,
    getData
}
使用
import { a,getDate } form './db'
getData();
import { a,getData as get} form './db'
get();

定義 db.ts
exprot default function getData(value:string):string {
    return value
}
使用
import getData form './db'
getData();

11.命名空間

  • 命名空間和模塊的區別: 命名空間,內部模塊,主要用於組織代碼,避免命名衝突。 模塊,ts的外部模塊的簡稱,側重代碼的複用,一個模塊裏可能會有多個命名空間。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
namespace A {
    interface Animal {
        name:string;
        eat(str:string):void;
    }
    export class Dog implements Animal {
        name: string;
        constructor(name:string) {
            this.name = name;
        }
        eat() {
            return `喫骨頭`;
        }
    }
}
var dog = A.Dog("小黑");
dog.eat();

命名空間封裝成模塊
a.ts文件名
定義
export namespace A {
    interface Animal {
        name:string;
        eat(str:string):void;
    }
    export class Dog implements Animal {
        name: string;
        constructor(name:string) {
            this.name = name;
        }
        eat() {
            return `喫骨頭`;
        }
    }
}
使用
import { a } from './a'
var dog = new a.Dog();
dog.eat();

12.裝飾器

  • 裝飾器: 裝飾器是一種特殊類型的聲明,它能夠被附加到類聲明,方法,屬性或參數上,可以修改類的行爲。
  • 通俗的講裝飾器就是一個方法,可以注入到類、方法、屬性參數上來擴展類、屬性、方法、參數的功能。
  • 常見的裝飾器有: 類裝飾器、屬性裝飾器、方法裝飾器、參數裝飾器。
  • 裝飾器寫法: 普通裝飾器(無法傳參)、裝飾器工廠(可傳參)。
  • 裝飾器是過去幾年中js最大的成就之一,已經是Es7的標準特性之一。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
1.類裝飾器(普通裝飾器,無法傳參)
function logClass(params:any){
    console.log(params);
    params.prototype.apiUrl="動態擴展的屬性";
    params.prototype.run = function() {
        console.log("我是run方法");
    }
}
@logClass
httpClient {
    constructor() {

    }
    getData() {

    }
}
var H = new httpClient();
console.log(H.apiUrl);
H.run();

2.類裝飾器(裝飾器工廠,可傳參)
function logClass(params:string){
    return function(target:any) {
        target.prototype.apiUrl="動態擴展的屬性";
        target.prototype.run = function() {
            console.log("我是run方法");
        }
    }
}
@logClass('hello')
httpClient {
    constructor() {

    }
    getData() {

    }
}

把類賦值給target
把參數賦值給params

var H:any = new httpClient();
console.log(H.apiUrl);
H.run();

類裝飾器重載以前類的構造函數
function logClass(target: any) {
    console.log(target);
    return class extends target{
        apiUrl:any = "我是修改後的url";
        getData() {
            console.log(this.apiUrl);
        }
    }
}
@logClass
httpClient {

    public apiUrl: string | undefined;
    constructor() {
        this.apiUrl = 'url';
    }
    getData() {
        console.log(this.apiUrl);
    }
}
var http = new httpClient();

------------------------------
3.屬性裝飾器(屬性裝飾器表達式會在運行時當作函數調用,傳入下列兩個參數,對於靜態成員來說是類的構造函數,對於實例成員是類的原型對象)
function logClass(params:any){
    console.log(params);
    params.prototype.apiUrl="動態擴展的屬性";
    params.prototype.run = function() {
        console.log("我是run方法");
    }
}
function logProperty(params:string){
    return function(target: any,attr:any) {
        console.log(target);
        console.log(target[attr]);
        target[attr] = params;
    }
}
@logClass('xxx')
httpClient {
    @logProperty("http://baidu.com");
    public url: string | undefined;
    constructor() {
        
    }
    getData() {
        console.log(this.url);
    }
}
var http = new httpClient();
http.getData();

4.方法裝飾器
它會被應用到的方法的屬性描述符上,可以用來監視,修改或者替換方法定義
方法裝飾器會在運行是傳入下列3個參數
(1)對於靜態成員來說類的構造函數,對於實例成員來說是類的原型對象。
(2)成員的名字。
(3)成員的屬性描述符。

function logMethod(params: any) {
    return function(target:any,methodName:any,desc:any) {
        console.log(target);
        console.log(methodName);
        console.log(desc);
        target.apiUrl="動態擴展的屬性";
        target.run = function() {
            console.log("我是run方法");
        }
    }
}

httpClient {
    constructor() {
        
    }
    @logMethod("http://baidu.com")
    getData() {
        console.log(this.url);
    }
}
var http:any = new httpClient();
http.run();

------------------------------------------

function logMethod(params: any) {
    return function(target:any,methodName:any,desc:any) {
        console.log(target);
        console.log(methodName);
        console.log(desc);
        //修改裝飾器的方法 把裝飾器方法傳入所以參數改爲string類型
        //保存當前的方法
        var oMethod = desc.value;
        desc.value = function(...args:any[]) {
            args = args.map((value)=>{
                return String(value)
            });
            console.log(args);
        }
    }
}

httpClient {
    public url:any | undefined;
    constructor() {
        
    }
    @logMethod("http://baidu.com")
    getData() {
        console.log(this.url);
    }
}
var http:any = new httpClient();
http.getData(123,'xxx');

每天進步一點點,更多精彩內容,歡迎關注公衆號“編程社”!!!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章