一、準備


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.函數

聲明函數
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.類

基本模型
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.繼承

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 (靜態方法裏面不能直接調用類裏面的屬性,能調用靜態屬性)
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.多態

  • 父類定義一個方法不去實現,讓繼承它的子類去實現,讓每一個子類有不同的表現
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必須放在抽象類裏面
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.接口

  • 定義規範 定義行為和動作的規範 (接口不關心類內部的數據狀態和方法實現的細節)
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.泛型

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引用模塊裏面的數據(變量,函數,類)。
定義 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的外部模塊的簡稱,側重代碼的複用,一個模塊裏可能會有多個命名空間。
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.類裝飾器(普通裝飾器,無法傳參)
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');