TypeScript基本知識點整理(看完絕對入門---真的!!)

本片文章主要講述了TypeScript的基礎知識點,這些是我我的的理解,若有不正確的地方請評論斧正!java

文章如下面的順序講解:node

  • 變量類型
  • 函數
  • 接口
  • 泛型
  • 命名空間
  • 聯合類型
  • 類型斷言

在開始以前咱們先裝環境:正則表達式

npm i typescript -g //全局安裝typescript

npm init -y //進入文件夾,初始化項目,生成package.json文件

tsc --init //建立tsconfig.json文件

npm i @types/node -S //這個主要是解決模塊的聲明文件問題
複製代碼

環境到此安裝結束;typescript

一,變量類型

1.number 類型npm

let num1 : number = 20;
let num2 : number = 175.5;
let a1 : number = Infinity; //正無窮大
let a2 : number = -Infinity; //負無窮小
let a3 : number = NaN;
複製代碼

注意:Infinity, -Infinity, NaN 也屬於Number類型json

2.undefined 類型數組

let un : undefined = undefined;
複製代碼

注意:bash

undefined 類型的數據只能被賦值爲 undefinedjsp

在 typescript中,已聲明未初始化的值要直接訪問的話,類型須要定義爲undefined函數

3.null 類型

let nu : null = null;
複製代碼

注意:

null 類型只能被被賦值爲null

null是一個空指針對象,undefined是未初始化的變量,因此,能夠把undefined當作一個空變量,把unll當作一個空對象。

特別注意: 默認狀況下,undefined 和 null 類型,是全部其它類型的子類型,也能夠說成,它倆能夠給全部其餘類型賦值。

4.string 類型

//值類型
let str : string = '你好!'
//引用類型
let str1 : String = new String('你好!')
複製代碼

5. boolean 類型

let boo : boolean = true;
let boo1 : boolean = false
複製代碼

6.symbol 類型

let sy : symbol = Symbol('bar');
複製代碼

注意: symbol類型的值是經過Symbol構造函數建立的。

7. 數組類型

//字面量
let arr1 : number[] = [1, 2]

//泛型---->至關於數組中每一個元素的類型
let arr2 : Array<string> = ['a', 's']

//構造函數
let arr3 : string[] = new Array('a', 's')

//聯合類型-->這裏的聯合類型的意思是,數組中元素的類型能夠是number 或 string,兩種都有也能夠
let arr4 : Array<number | string> = [2, 'a']
複製代碼

8.元組類型(tuple)

let tup : [string,number] = ['asdasd', 43233];
複製代碼

注意:

元組和數組看起來有點相似,可是,是有區別的

元組的長度是有限的,並且分別爲每個元素定義了類型

9. 枚舉類型(enum)

enum--->組織收集一組相關變量的方式。

數字枚舉

enum REN {
    // nan = 1 ----->初始化下標
    nan,
    nv,
    yao
}
console.log(REN.nan)//0
console.log(REN.nv)//1
console.log(REN.yao)//2
//使用數字枚舉時,TS 會爲枚舉成員生成反向映射
console.log(REN[2])// yao
複製代碼

注意:

數字的枚舉---->下標從0開始,也能夠自行設置枚舉成員的初始值,它們會依次遞增

字符串枚舉

enum SIJI {
    chun = '春',
    xia = '夏',
    qiu = '秋',
    dong = '冬'
}

console.log(SIJI.chun)//春
console.log(SIJI.xia)//夏
console.log(SIJI.qiu)//秋
console.log(SIJI.dong)//冬
複製代碼

注意:

字符串枚舉類型容許使用字符串來初始化枚舉成員,能夠是一個字符串字面量或者另外一個字符串的枚舉成員

字符串枚舉類型不支持成員自增加,每一個成員必須初始化,另外字符串枚舉不會爲成員生成發向映射

10. void 類型

void 類型--->表示沒有任何返回值,通常用於定義方法時方法沒有返回值

function f1() : void {
    console.log('void類型')
}
複製代碼

注意:

這裏你也能夠指定返回值類型爲 undefined。由於 JS 中,若是函數沒有返回值,則會默認返回 undefind。不過,使用 void 類型可使表意更清晰。

11. any 類型

注意: 其餘類型都是any類型的子類型 ,any類型的值能夠被賦值爲任何類型的值

let an : any = 'any 類型';
console.log(an)//any 類型
an = 25;
console.log(an)//25
複製代碼

注意:對於any 須要注意兩點

若是在聲明變量時,沒有聲明其類型,也沒有初始化,(由於類型推斷會自動判斷類型),那麼它就會被判斷爲any類型

let an1;
an1 = '沒有聲明其類型,也沒有初始化';
console.log(an1)//沒有聲明其類型,也沒有初始化
an1 = 25
console.log(an1)//25
複製代碼

在any類型變量上能夠訪問任何屬性,即便它不存在

let something: any = 42
something.mayExist()    // 沒問題,由於其可能在運行時存在
something.toFixed() // 沒問題,雖然確實存在,可是編譯器並不會去檢查
複製代碼

12. never 類型

注意:

never 表示永遠不會存在的值的類型, never 是任何類型的子類型,可是 沒有任何類型是never的子類型或能夠賦值給never類型(除了never自己以外)。 即便 any也不能夠賦值給never。

never 類型經常使用於兩種狀況

用於描述從不會有返回值的函數---》返回never的函數必須存在沒法達到的終點

function f5() : never {
    while (true) {
         // do something
     }
 }
複製代碼

用於描述總拋出錯誤的函數

function f2(msg : string) : never {
    throw new Error(msg)
}
複製代碼

13. 日期類型

let da : Date = new Date()
console.log(da)
複製代碼

14. 正則表達式類型

//構造函數聲明法
let reg1 : RegExp = new RegExp('ljy','gi')
console.log(reg1)

//字面量的聲明法
let reg2 : RegExp = /ljy/gi
console.log(reg2)
複製代碼

二, 函數

1. 函數定義

定義函數有函數聲明和函數表達式兩種形式。定義函數的參數和返回值能夠指定其類型;當調用函數時,傳入參數類型必須與定義函數參數類型保持一致。

函數聲明定義

//            參數類型    返回值類型
function f(age:number) : string {
    return `找到了${age}的小哥哥`;
}

let age : number = 22;
let res : string = f(age);
console.log(res)
複製代碼

函數表達式定義

let f1 = (age:number) : string => {
    return `找到了${age}的小哥哥`;
}
let age1 :number = 21;
let res1 : string = f1(age1);
console.log(res1)
複製代碼

注意:表達式定義完之後,必須調用函數

函數表達式還有一種寫法: 函數表達式:指定變量fn的類型

注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>

在 TypeScript 的類型定義中,=> 用來表示函數的定義,左邊是輸入類型,須要用括號括起來,右邊是輸出類型。

// let fn: (x: Type, y: Type) => Type = (x, y) => {}

//例子
var run3: (x: number, y: number) => string = function(x: number, y: number): string{
    return 'run3';
}
console.log(run3(1, 2))


//當給變量run3指定類型的時候,應該是函數的參數和返回值的約束類型。若是用後面學到的ts類型推論,能夠簡寫爲:

var run4: (x: number, y: number) => string = function(x, y){ 
// 類型推論能夠肯定函數的參數和返回值類型,也就能夠省略類型指定
    return 'run4';
}
console.log(run4(1, 2))
複製代碼

2. 函數沒有返回值可使用void類型值定返回值

function  f3() : void {
    console.log('沒有返回值')
}
f3()
複製代碼

3. 可選參數的函數

注意:可選參數必定要放在參數的最後面

function f4(age:number, cm?:number) : string {
    //cm爲可選參數,可傳可不傳
    if (cm) {
        return `可選參數------身高爲${cm}釐米`;
    } else {
        return `可選參數-----年齡${age}歲`
    }
}
console.log(f4(12))
console.log(f4(24, 175))
複製代碼

4. 有默認值參數的函數

注意:ts會將添加了默認值的參數識別爲可選參數,有默認值的參數的位置不受【可選參數必須放在後面】的限制

function f5(age:number, cm:number = 188) : string {
    return `默認參數----年齡爲${age}歲---身高爲${cm}cm`
}
console.log(f5(25))
複製代碼

5. 剩餘參數的函數

//當有不少參數的時候,或者參數個數不肯定,能夠用三點運算符
function f6(...rest:number[]) : number[] {
    return [...rest];
}
console.log(f6(1,2,3,4,5,6,7,8,9))

function f7(a:number, b:number, ...rest:number[]) : number[] {
    return [a, b, ...rest]
}

console.log(f7(100,200,1,2,3,4,5,6))
複製代碼

6. 接口中的函數

第一種寫法

interface int1 {
    say (age:number) : void  //抽象方法
}
複製代碼

第二種寫法

interface int2 {
    say : (age:number) => void  //抽象方法
}
複製代碼

7.函數的重載

注意:

先聲明全部方法重載的定義,不包含方法的實現

再聲明一個參數爲any類型的重載方法

實現any類型的方法並經過參數類型(和返回類型)不一樣來實現重載

typescript中的重載:經過爲同一個函數提供多個函數類型定義來實現多種功能的目的

TypeScript 會優先從最前面的函數定義開始匹配,因此多個函數定義若是有包含關係,須要優先把精確的定義寫在前面。

function f1(x: number, y: number): number;
function f1(x: string, y: string): string;

// 上面定義函數的格式,下面定義函數的具體實現
function f1(x: any, y: any): any {
    return x + y;
}

f1(1, 2);
f1('a', 'b');
複製代碼

三, 類

1. 訪問修飾符

public:公共修飾符

注意:

表示屬性或方法都是公有的,在類的內部,子類的內部,類的實例都能被訪問,默認狀況下,爲public

class People {
    public name : string
     constructor (name:string) { //構造函數必須寫
        this.name = name
    }
    public say () :void {
        console.log('你好')
    }
}
複製代碼

private 私有修飾符

注意:

表示在當前類中能夠訪問,子類,外部類不能夠訪問

class People {
    private name : string
     constructor (name:string) { //構造函數必須寫
        this.name = name
    }
    private say () :void {
        console.log('你好')
    }
}
複製代碼

protected 保護類型

注意:

表示在當前類中和子類中能夠訪問,外部類不能夠訪問

class People {
    protected name : string
     constructor (name:string) { //構造函數必須寫
        this.name = name
    }
    protected say () :void {
        console.log('你好')
    }
}
複製代碼

注意:

TypeScript 只作編譯時檢查,當你試圖在類外部訪問被 private 或者 protected 修飾的屬性或方法時,TS 會報錯,可是它並不能阻止你訪問這些屬性或方法。

readonly 只讀修飾符

注意:

表示某個屬性是隻讀的,不能被修改

class People {
    readonly name : string
     constructor (name:string) { //構造函數必須寫
        this.name = name
    }
}
複製代碼

2. 聲明類

class People {
    name : string //默認爲public
    age : number
    constructor (name:string, age:number) { //構造函數必須寫
        this.name = name
        this.age = age
    }
    say () :void {
        console.log('你好')
    }
}

const HH : People = new People('含含', 21)
console.log(HH.name)
console.log(HH.age)
HH.say()
複製代碼

3. 類的繼承

class Student extends People {
     cm : number
    constructor (name:string, age:number, cm:number) {
        super(name, age) //super 繼承父類的構造函數,並向構造函數傳參,super必須寫在第一行
        this.cm = cm
    }
    work () : void {
        console.log('學習')
    }
}

const  stu1 : Student = new Student('liu', 22, 175)
console.log(stu1.name)
console.log(stu1.age)
console.log(stu1.cm)
stu1.say()
stu1.work()
複製代碼

4. 靜態屬性和靜態方法

注意:

靜態方法和靜態屬性必須使用類名調用

靜態屬性和靜態方法在實例化以前就已經存在

class People {
    static name1 : string = '靜態屬性';
    static say () :void {
        console.log('靜態方法')
    }
}
console.log(People.name1)
People.say()
複製代碼

注意:靜態方法調用不了實例化方法和實例化屬性,由於靜態域加載是在解析階段,而實例化是在初始化階段,(java原理),因此靜態方法裏面不能調用本類的方法和屬性,能夠調用靜態屬性和靜態方法

5. 多態

多態---->重寫方法

父類定義一個方法不去實現,讓繼承它的子類去實現,每一個子類的該方法有不一樣的表現

class Animal {
    name : string
    constructor (name:string) {
        this.name = name
    }
    eat () : void {
        //讓它的子類去實現不一樣的eat方法
    }
}

class Laohu extends Animal {
    constructor (name:string) {
        super(name)
    }
    eat () : void {
        console.log(`${this.name}吃肉!`)
    }
}

class Laoshu extends Animal {
    constructor (name:string) {
        super(name)
    }
    eat () : void {
        console.log(`${this.name}吃糧食!`)
    }
}
const laohu : Laohu = new Laohu('老虎')
laohu.eat()
const  laoshu : Laoshu = new Laoshu('老鼠')
laoshu.eat()
複製代碼

6. 類和接口

注意:

類能夠實現(implement)接口。經過接口,你能夠強制地指明類遵照某個契約。你能夠在接口中聲明一個方法,而後要求類去具體實現它。

接口不能夠被實例化,實現接口必須重寫接口中的抽象方法

interface Play {
    plays (difang:string) : void;
}

class Playy implements Play {
    plays(difang: string): void {
        console.log(`咱們要去${difang}玩!!!`)
    }
}

const pl : Playy = new Playy();
pl.plays('北京')
複製代碼

注意:類和接口的區別

類能夠實現(implement)多個接口,但只能擴展(extends)自一個抽象類。

抽象類中能夠包含具體實現,接口不能。

抽象類在運行時是可見的,能夠經過 instanceof判斷。接口則只在編譯時起做用。

接口只能描述類的公共(public)部分,不會檢查私有成員,而抽象類沒有這樣的限制。

7. 抽象類和抽象方法

注意:

用abstract關鍵字定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實現而且必須在派生類(抽象類的子類)中實現

抽象類:它是提供其餘類繼承的基類,不能直接被實例化,子類繼承能夠被實例化

abstract修飾的方法(抽象方法)只能放在抽象類裏面

抽象類和抽象方法用來定義標準(好比定義標準爲:抽象類Animal有抽象方法eat,要求它的子類必須包含eat方法)

abstract class People {
    name : string
    constructor (name:string) {
        this.name = name
    }
    abstract eat (food:string) :void;//抽象方法不包括具體實現,而且必須再派生類中實現
}

class Stud1 extends People {
    //抽象類的子類必須實現抽象類中的抽象方法
    constructor (name:string) {
        super(name)
    }
    eat(food: string): void {
        console.log(`我愛吃${food}`)
    }

}

const stu11 : Stud1 = new Stud1('liu')
stu11.eat('麪條')
複製代碼

四,接口

注意:

接口定義:接口是對傳入參數進行約束;或者對類裏面的屬性和方法進行聲明和約束,實現這個接口的類必須實現該接口裏面屬性和方法;typescript中的接口用interface關鍵字定義。

接口做用:接口定義了某一批類所須要遵照的規範,接口不關心這些類的內部狀態數據,也不關心這些類裏方法的實現細節,它只規定這批類裏必須提供某些方法,提供這些方法的類就能夠知足實際須要。typescrip中的接口相似於java,同時還增長了更靈活的接口類型,包括屬性、函數、可索引和類等。

1. 屬性接口

對傳入對象的約束,也就是json數據

interface Sx {
    name : string
    age : number
}

function f8(peop:Sx) {
    //name age 必須傳遞
    console.log(peop)
}

const obj = {
    name : 'liu',
    age : 25
}
f8(obj)
複製代碼

2. 函數類型的接口

對方法傳入的參數和返回值進行約束

interface Sta {
    (difang : string, todo : string) : string
}

let play : Sta = (difang:string, todo:string) : string => {
    return `咱們去${difang}${todo}`
}

console.log(play('灞橋', '吃燒烤'))
複製代碼

3. 可索引的接口

對索引和傳入的參數的約束

//對數組的約束
interface UserArr {
    //索引爲number,參數爲string
    [index : number] : string
}

const arr : UserArr = ['a', 'b']
console.log(arr)

//對 對象的約束
interface UserObj {
    [index : number] : number
}

const obj1 : UserObj = { 2:1, 3:4 }
console.dir(obj1)
複製代碼

4. 類 類型接口

對類的約束

interface Anmal {
    //對類裏面的屬性和方法進行約束
    name : string
    eat (food:string) : void
}
//類實現接口要用implements , 子類必須實現接口裏面聲明的屬性和方法
class Laoshu implements Anmal{
    name : string
    constructor (name : string) {
        this.name = name
    }
    eat(food:string):void {
        console.log(`${this.name}${food}`)
    }
}
const lao : Laoshu = new Laoshu('老鼠')
lao.eat('糧食')
複製代碼

5. 接口繼承

//父類Anmal看上面
//實現LaoHu的這個接口,必須也要實現LaoHu繼承的Anmal接口中的方法
interface LaoHu extends Anmal{
    say (sa : string) : void
}
//繼承並實現接口
class XiaoLaoHu implements LaoHu{
    name : string
    constructor (name : string) {
        this.name = name
    }
    eat (food : string) : void {
        console.log(`${this.name}${food}`)
    }
    say(sa: string): void {
        console.log(`${this.name}${sa}`)
    }
}

const xiao : XiaoLaoHu = new XiaoLaoHu('老虎')
xiao.eat('肉')
xiao.say('你好')
複製代碼

五, 泛型

注意:

不少時候,類型是寫死的,不利於複用,泛型能夠簡單的理解爲給類型的這種值設置變量,解決類,接口

方法的複用性,以及對不特定數據類型的支持

語法 : <類型變量名> 通常是單字母大寫

1. 泛型函數

函數再調用時,指定泛型T的類型

function f9<T>(value:T) : T {
    //傳入參數類型爲T,返回值的類型也爲T
    console.log(`我傳入了${value}`)
    return value
}

f9<number>(10)

function f10 <T> (value:T) : any {
    //傳入參數的類型爲T,返回任意類型的值
    console.log(`我返回了${value}`)
    return `我返回了${value}`
}

console.log(f10<string>('我是ljy'))
複製代碼

2. 泛型類

泛型類,使用 < > 跟在類名後面

class Ni <T> {
    name : T
    constructor (name : T) {
        this.name = name
    }
    say (value : T) : any {

        return `${this.name}${value}`
    }
}

const ni1 = new Ni<string>('ljy')//實例化類,指定類的類型是string
console.log(ni1.say('你好'))

const ni2 = new Ni<number>(20)//實例化類,指定類的類型是number
console.log(ni2.say(23))
複製代碼

3. 泛型接口

第一種

interface Niniubi {
    <T> (value:T) : any
}

let fff : Niniubi = <T>(value : T) : any => {
    return `我傳入了${value}`
}
console.log(fff<number>(25))
console.log(fff<string>('ljy'))
複製代碼

第二種

interface ConfigFnTwo<T>{
    (value:T):T;
}
function setDataTwo<T>(value:T):T{
    return value
}
var setDataTwoFn:ConfigFnTwo<string> = setDataTwo
setDataTwoFn('name');
複製代碼

4.在泛型約束中使用類型參數

有時,咱們想讓參數的類型是某個對象的屬性時,能夠這樣寫:

function getProperty<T, k extends keyof T>(obj:T, key: K) {
    return obj[key]
}

let obj = { a: 1, b: 2, c: 3}
getProperty(obj, "a"); // true
getProperty(obj, "t"); // error: Argument of type '"t"' is not assignable to
                                parameter of type '"a" | "b" | "c"'.
複製代碼

錯誤的緣由:首先keyof T就等於"a" | "b" | "c",而後K extends就至關於K在keyof T中,這就是約束。

六,命名空間

namespace Shuaige {
    export class DeHua {
        public name : string = '劉德華'
        say () {
            console.log(`我是${this.name}`)
        }
    }
}

namespace Bajie {
    export class DeHua {
        public name : string = '馬德華'
        say () {
            console.log(`我是${this.name}`)
        }
    }
}


const de : Shuaige.DeHua = new Shuaige.DeHua()
de.say()

const de1 : Bajie.DeHua = new Bajie.DeHua()
de1.say()
複製代碼

七, 聯合類型

聯合類型表示一個值能夠是幾種類型之一,咱們使用( | )分隔每一個類型

聯合類型的變量在被賦值的時候,會根據類型推論的規則推斷出一個類型

若是一個值是聯合類型,咱們只能訪問此聯合類型的全部類型裏面共有的成員

let ddd : string | number
ddd = 'nihao'
console.log(ddd.length)//ddd被推斷成了 string,訪問它的 length 屬性不會報錯
console.log(`聯合類型${ddd}`)
ddd = 255
console.log(`聯合類型${ddd}`)
console.log(ddd.length)//報錯 ddd被推斷成了 number,訪問它的 length 屬性時就報錯了
//ddd = false                   err
//console.log(`聯合類型${ddd}`)  err
複製代碼

1. 訪問聯合類型的屬性或方法

當 TypeScript 不肯定一個聯合類型的變量究竟是哪一個類型的時候,咱們只能訪問此聯合類型的全部類型裏共有的屬性或方法:

function f11(name : string, age : string | number) {
     console.log(age.length)//報錯
 }
f11('ljy', '21')

報錯:Property 'length' does not exist on type 'string | number'.Property 'length' does not exist on type 'number'.
複製代碼

上例中,length 不是 string 和 number 的共有屬性,因此會報錯。因此只能訪問類型的共有的屬性或方法

function f12(name : string, age : string | number) {
    console.log(age.toString)
}
f12('ljy', 21)
複製代碼

八, 類型斷言

注意:類型斷言(Type Assertion)能夠用來手動指定一個值的類型。

語法:

<類型>值
 或
值 as 類型
複製代碼

類型斷言的用法如上,在須要斷言的變量前加上 便可

就剛纔上邊TypeScript 不肯定一個聯合類型的變量究竟是哪一個類型的時候來講

function f13(name : string, age : string | number) {
     if (age.length) { //報錯
         console.log(age.length) //報錯
     }  else {
         console.log(age.toString)
     }

 }

 f13('ljy', 21)//Property 'length' does not exist on type 'string |number'.Property 'length' does not exist on type 'number'
複製代碼

此時可使用類型斷言,將 age 斷言成 string

function f14(name : string, age : string | number) {
    if ((<string>age).length) {//斷言
        console.log((<string>age).length)//斷言
    }  else {
        console.log(age.toString)
    }

}
f14('ljy', 21)
複製代碼

類型斷言不是類型轉換,斷言成一個聯合類型中不存在的類型是不容許的:

function toBoolean(something: string | number): boolean {
     return <boolean>something;
 }
Type 'string | number' cannot be converted to type 'boolean'
複製代碼

本人通過閱讀,ts官方文檔,jspang的ts教程,Hopsken的ts教程,Staticy的ts教程,才入門的,再此感謝!

相關文章
相關標籤/搜索