TypeScriptz學(xué)習(xí)筆記

TypeScriptz學(xué)習(xí)筆記

標(biāo)簽(空格分隔): TypeScript 撩課學(xué)院


安裝TypeScript

cnpm install -g typescript
tsc -v  // 查看版本

TypeScript初體驗(yàn)

1. 類型注解

function log(msg) {
    console.log('hello' + msg);
}
log('itlike');
log(10);

2. 接口

interface Person {
    name: string,
    sex: string,
    age: number
}

function logPerson(person: Person){
    console.log(`姓名: ${person.name}, 性別: ${person.sex}, 年齡: ${person.age}`)
}

let xl = {
    name: '小撩',
    age: 25,
    sex: '女'
}

logPerson(xl);

3. 類

class Dog {
    dogName: string;
    dogAge: number;
    dogSex: string;
    
    constructor(dogName: string, dogAge: number, dogSex: string){
        this.dogName = dogName;
        this.dogAge = dogAge;
        this.dogSex = dogSex;
    }
    
    eat(foods: string){
        console.log(this.dogName + '在吃' + foods)
    }
}

let wc = new Dog('旺財(cái)', 6,'公');
console.log(wc);
wc.eat("蔬菜");

基礎(chǔ)類型

1. 字符串

let dogName: string = '旺財(cái)';
let dogSex: string = '公';
let dogAge: number = 5;

let introDog: string = `
    我有一只小狗弧岳,它叫${dogName},
    它今年${dogAge}歲凳忙,它是
    ${dogSex}的
`

console.log(introDog);

2. 數(shù)字

// 2 8 10 16 進(jìn)制
let num1: number = 16;
let num2: number = 0x10;
let num3: number = 0o20;
let num4: number = 0b10000;

console.log(num1, num2, num3, num4);

3. 布爾

let flag:boolean = false;
console.log(flag);

4. 數(shù)組

let numArr: number[] = [1,2,3];
let strArr: string[] = ['張三', '李四', '王五'];
console.log(numArr, strArr);

let boolArr: Array<boolean> = [true, false];
console.log(boolArr);

5. 元組

let tuple: [string, number, boolean, string];
tuple = ['上海', 200, true, '北京'];
console.log(tuple);

let tuple1: [string, number, boolean, string] = ['上海', 200.232323, true, '北京'];
console.log(tuple1[0]);
console.log(tuple1[0].length);
console.log(tuple1[1].toFixed());
console.log(tuple1[2].valueOf());
console.log(tuple1[3].substr(1));

6. 枚舉

自動(dòng)賦值

enum Sex {
    Man,
    Women
}

let sex1: Sex = Sex.Women;
let sex2: Sex = Sex.Man;
console.log(sex1, sex2);

手動(dòng)賦值

enum Sex {
    Man = 2,
    Women = 8
}

let sex1: Sex = Sex.Women;
let sex2: Sex = Sex.Man;
console.log(sex1, sex2);

通過枚舉的值得到名字

enum Sex {
    Man = 2,
    Women = 8
}

let sexName: string = Sex[2];
console.log(sexName);

7. any

let str: any;
str = '我是小撩寶寶';
str = 100;
str = true;

let arr: any[] = ['張三', 19, true, '男'];
arr[3] = 2;
console.log(arr);

8. void

// let str: void = 10; //報(bào)錯(cuò)
let str1: void = null;
let str2: void = undefined;

console.log(str1, str2);

function logMsg(): void {
    console.log('it like, like it');
}

logMsg();

9. null和undefined

let str1: null = null;
let str2: undefined = undefined;
let str3: null = undefined;
let str4: undefined = null;
let str5: string = null;
let str6: string = undefined;

console.log(str1, str2, str3, str4, str5, str6);

10. never

function error(msg:string): never{
    throw new Error(msg);
}

// error('發(fā)生未知錯(cuò)誤');

// 必須存在無法到達(dá)的終點(diǎn)

function func():never {
    while(true){
        console.log(1);
    }
}

func();

11. object

object的一般使用

let obj1:object = {name: '小撩', age: 18};
console.log(obj1);
console.log(obj1.toLocaleString);


let obj = [1, 2, 3];
console.log(obj);

規(guī)定declare函數(shù)的參數(shù)必須是object

declare function func(o: object): void

func({name: '小撩'}) //OK
func([1,2,3]) //OK
func(null) //OK
func(undefined) //OK

func(123); //報(bào)錯(cuò)
func('小撩'); //報(bào)錯(cuò)
func(true); //報(bào)錯(cuò)

12. 類型斷言

方式一:<>判斷該object是string類型

let obj: any = 'like it, it like';

// let str: string = obj.substr(0, 3);
// console.log(str);

let str2: string = (<string>obj).substr(0, 3);
let str3: string = (<string>obj).toFixed(2);
console.log(str2);
console.log(str3);

方式二:as判斷該object是string類型

let obj: any = 'like it, it like';
let str4: string = (obj as string).substr(0, 4);
console.log(str4);

聲明和解構(gòu)

1. var和let

// 1. var和let
// var存在的幾個(gè)問題
// ①:僅在函數(shù)中才是塊級(jí)作用域
// ②:變量提升
// 因此現(xiàn)在建議多多使用let

var str:string = '撩課';
let str1:string = 'itlike';


// 塊級(jí)作用域
function func(flag: boolean): number{
    let a = 99;
    if(flag){
        // let b = a + 1;
        var b = a + 1;
        console.log(b);
        return b;
        
    }
    console.log(b);
    return b;
}

func(false);

// 注意
function funcA(x){
    let x = 100; //不OK,重復(fù)聲明同一個(gè)變量
    var x = 100; //不OK缩筛,重復(fù)聲明同一個(gè)變量
}

function funcB(flag: boolean, x:number): void {
    if(flag){
        let x = 100; //OK消略,因?yàn)閘et是塊級(jí)作用域堡称,在if里面
    }
}

2. const

const CAT_NAME: string = "喵喵";
// CAT_NAME = "哈哈哈"; //錯(cuò)誤

const CAT = {
    name: CAT_NAME,
    age: 8
}

console.log(CAT);

// 錯(cuò)誤

// CAT = {
//  name: '小可愛',
//  age: 1
// }

CAT.name = "小黑黑";

console.log(CAT);

3. 解構(gòu)

數(shù)組的解構(gòu)

let arr:number[] = [1,2];
let [one, two] = arr;
console.log(one, two);
// 交換兩個(gè)變量的數(shù)值瞎抛,但是這種方式不嚴(yán)謹(jǐn),盡量少用
[one, two] = [two, one];
console.log(one, two);

// ...符號(hào)
let [first, ...reset] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(reset); // [2, 3, 4, 5]

對(duì)象的解構(gòu)

enum Sex {
    Man,
    Women
}

interface Person {
    personName: string,
    personAge: number,
    personSex: Sex
}

let person: Person = {
    personName: '小撩',
    personAge: 19,
    personSex: Sex.Women
}

let {personName, personAge, personSex} = person;
console.log(personName, personAge, personSex);

接口

1. 接口的定義和使用

interface Person {
    pName: string,
    pAge: number,
    pJob: string
}

// 初始化person的時(shí)候却紧,變量的順序是無所謂的桐臊,但是名稱和類型必須和接口保持一致
let person: Person = {
    pName: '小撩',
    pAge: 18,
    pJob: '咨詢小姐姐'
}

function printPerson(person){
    console.log(`我是:${person.pName}`)
}

printPerson(person);

2. 接口-可選屬性

好處:

    1. 對(duì)某些屬性進(jìn)行預(yù)定義
    1. 捕獲錯(cuò)誤
// 輸出接口
interface Circle {
    color: string, // 顏色
    area: number   //面積
}

// 輸入接口
interface CircleConfig {
    // 可選屬性
    color?: string,
    radius?: number
}

function createCircle(config: CircleConfig): Circle{
    let newCircle = {color: 'green', area: 100};
    if(config.color){
        newCircle.color = config.color;
    }
    if(config.radius){
        newCircle.area = Math.PI * config.radius * config.radius;
    }
    return newCircle;
}

let myCircle1 = createCircle({radius: 100});
console.log(myCircle1);

let myCircle2 = createCircle({color: 'red'});
console.log(myCircle2);

3. 只讀屬性

interface FullName {
    readonly firstName: string,
    readonly lastName: string
}

let p: FullName = {firstName: '張', lastName: '三豐'};
console.log(p);
console.log(p.firstName, p.lastName);
p.firstName = '李'; // 只讀接口只能進(jìn)行一次賦值胎撤,第二次就會(huì)報(bào)錯(cuò)
console.log(p);
console.log(p.firstName, p.lastName);

只讀數(shù)組

// TS ReadonlyArray<T> Array<T>
let arr:number[] = [1,2,3,4];
arr.push(10);
// arr.pop();
console.log(arr);

let ra: ReadonlyArray<number> = arr;
// ra.push(5); //error
// ra[0] = 10; //error
// ra.length = 1000; //error
console.log(ra);

// 重新將ra賦值給arr,可以使用斷言
arr = ra as number[];
console.log(arr);

4. 額外的類型檢查

4.1 使用斷言

// 輸出接口
interface Circle {
    color: string, // 顏色
    area: number   //面積
}

// 輸入接口
interface CircleConfig {
    // 可選屬性
    color?: string,
    radius?: number
}

function createCircle(config: CircleConfig): Circle{
    let newCircle = {color: 'green', area: 100};
    if(config.color){
        newCircle.color = config.color;
    }
    if(config.radius){
        newCircle.area = Math.PI * config.radius * config.radius;
    }
    return newCircle;
}

// 這種方式是無法給添加一個(gè)接口中沒有的屬性的
// let myCircle1 = createCircle({color: 'red', radiussss: 100});
// 1. 使用類型斷言
let myCircle1 = createCircle({color: 'red',radius: 11, radiussss: 100} as CircleConfig);
console.log(myCircle1);

4.2 通過字符串的索引簽名(推薦)

// 輸出接口
interface Circle {
    color: string, // 顏色
    area: number   //面積
}

// 輸入接口
interface CircleConfig {
    // 可選屬性
    color?: string,
    radius?: number,
    // 字符串的索引簽名
    [propsName: string]: any
}

function createCircle(config: CircleConfig): Circle{
    let newCircle = {color: 'green', area: 100};
    if(config.color){
        newCircle.color = config.color;
    }
    if(config.radius){
        newCircle.area = Math.PI * config.radius * config.radius;
    }
    return newCircle;
}

let myCircle1 = createCircle({color: 'red',radius: 11, radiussss: 100, a: 'q', c: 10});

4.3 對(duì)象賦值

// 輸出接口
interface Circle {
    color: string, // 顏色
    area: number   //面積
}

// 輸入接口
interface CircleConfig {
    // 可選屬性
    color?: string,
    radius?: number,
}

function createCircle(config: CircleConfig): Circle{
    let newCircle = {color: 'green', area: 100};
    if(config.color){
        newCircle.color = config.color;
    }
    if(config.radius){
        newCircle.area = Math.PI * config.radius * config.radius;
    }
    return newCircle;
}

let circleOption = {color: 'red',radius: 11, radiussss: 100, a: 'q', c: 10};
let myCircle1 = createCircle(circleOption);

5. 函數(shù)類型

interface CompareFunc {
    (first: number, last: number): boolean
}

// let myCompare: CompareFunc = function(first: number, last: number): boolean {
//  return first > last;
// }

// let myCompare: CompareFunc = function(a: number, b: number): boolean {
//  return a > b;
// }

let myCompare: CompareFunc = function(a, b) {
    return a > b;
}

console.log(myCompare(10,20));

6. 可索引類型

interface StrArr {
    [index: number]: string
}

let myArr:StrArr = ['it', 'like'];
let str:String = myArr[1];
console.log(str);

7. 類類型

7.1 屬性

interface ClockInterface{
    currentTime: Date;
}

class Clock implements ClockInterface {
    currentTime: Date;
    constructor(h: number, m: number){
        console.log(h, m);
    }
}

7.2 描述一個(gè)方法

interface ClockInterface{
    currentTime: Date;
    setTime(d: Date)
}

class Clock implements ClockInterface {
    currentTime: Date;
    constructor(h: number, m: number){
        console.log(h, m);
    }
    setTime(d: Date){
        console.log(d);
    }
}

8. 類的靜態(tài)部分 和 實(shí)例部分

8.1 靜態(tài)部分的類型

interface ClockConstructor {
    new {h: number, m: number}
}

class Clock implements ClockConstructor {
    constructor(h: number, m: number){
        
    }
}

8.2 實(shí)例類型

9. 接口繼承

interface Animal {
    // 品種
    breed: string
}

interface Cat extends Animal {
    // 顏色
    color: string
}

let cat = {} as Cat;
cat.breed = '藍(lán)貓';
cat.color = '白色';
console.log(cat);

9.1 一個(gè)接口繼承多個(gè)接口

interface Animal {
    // 品種
    breed: string
}

interface Mammal {
    // 腿的數(shù)量
    leg: number
}

interface Cat extends Animal,Mammal {
    // 顏色
    color: string
}

let cat = {} as Cat;
cat.breed = '藍(lán)貓';
cat.leg = 4;
cat.color = '白色';
console.log(cat);

1. 基本使用

var Cat = /** @class */ (function () {
    function Cat(catName) {
        this.catName = catName;
    }
    Cat.prototype.say = function () {
        return '大家好断凶,我是: ' + this.catName;
    };
    return Cat;
}());
var cat = new Cat('小黑貓');
console.log(cat);

2. 繼承

class Animal{
    animalName: string;
    constructor(animalName: string){
        this.animalName = animalName;
    }
    logName(){
        return '大家好伤提,我是: ' + this.animalName;
    }
}

class Dog extends Animal {
    // 品種
    breed: string;
    constructor(dName: string, breed: string){
        super(dName);
        this.breed = breed;
    }
    logBreed(){
        return `我的品種是${this.breed}`
    }
}

let dog = new Dog('小土豆', '土狗');
console.log(dog);
console.log(dog.animalName, dog.breed);
console.log(dog.logName());
console.log(dog.logBreed());

3. 子類重寫父類中的方法

class Animal{
    name: string;
    constructor(name: string){
        this.name = name;
    }
    // 走動(dòng)
    move(distance: number = 0){
        console.log(`${this.name}走動(dòng)了${distance}m`)
    }
}

class Snake extends Animal {
    constructor(name: string){
        super(name);
    }
    
    // 走動(dòng)
    move(distance: number = 10){
        console.log(`我是爬行的......`);
        // 調(diào)用父類的方法
        super.move(distance);
    }
}

class Horse extends Animal {
    constructor(name: string){
        super(name);
    }
    
    // 走動(dòng)
    move(distance: number = 500){
        console.log(`我是飛奔的......`);
        // 調(diào)用父類的方法
        super.move(distance);
    }
}

let snake:Snake = new Snake('小青蛇');
let horse:Animal = new Horse('白龍馬');

snake.move();
horse.move(70);

4. 公共、私有认烁、受保護(hù)肿男、只讀《修飾符》

4.1 公共的 public

// TS成員默認(rèn)都是public
class Animal{
    public name: string;
    public constructor(name: string){
        this.name = name;
    }
    public move(distance: number = 0){
        console.log(`${this.name}走動(dòng)了${distance}m`);
    }
}

4.2 私有的 private

class Animal{
    private name: string;
    constructor(name: string){
        this.name = name;
    }
    move(distance: number = 0){
        console.log(`${this.name}走動(dòng)了${distance}m`);
    }
}

let cat = new Animal('小花花');
console.log(cat);
cat.name = "小喵喵"; // 會(huì)報(bào)錯(cuò),name屬性是私有的却嗡,在實(shí)例對(duì)象中也無法使用
cat.move(100);

在TypeScript中舶沛,所有的類都是結(jié)構(gòu)性的

class Animal{
    private name: string;
    constructor(name: string){
        this.name = name;
    }
}

class Cat extends Animal{
    constructor(name: string){
        super('Cat');
    }
}

class Dog{
    private name: string;
    constructor(name: string){
        this.name = name;
    }
}

// 實(shí)例
let animal = new Animal('豬豬');
let cat = new Cat('小喵喵');
let dog = new dog('dog');

animal = cat;
animal = dog;
cat = dog;

4.3 受保護(hù)的 protected

class Person {
    protected name: string;
    constructor(name:string){
        this.name = name;
    }
}

class Employee extends Person{
    // 公司
    private company: string;
    constructor(name: string, company: string){
        super(name);
        this.company = company;
    }
    logMsg(){
        return `我叫${this.name}, 我在${this.company}工作`
    }
}

let p = new Employee('科比', 'NBA');
console.log(p.logMsg());

4.4 readonly修飾符

// 1) 可以使用'readonly'關(guān)鍵字將屬性設(shè)置為只讀的
// 2) 只讀屬性必須在聲明時(shí)或構(gòu)造函數(shù)里被初始化
class Person {
    readonly name: string;
    constructor(name: string){
        this.name = name;
    }
}

let person = new Person('小撩');
console.log(person.name);
person.name = '大撩'; // 會(huì)報(bào)錯(cuò)的,readonly修飾的屬性只能賦值一次

5. 參數(shù)屬性

// 參數(shù)屬性可以方便地讓我們在一個(gè)地方定義并初始化一個(gè)成員
// 1) 聲明和賦值合并至一處
// 2) 參數(shù)屬性通過給構(gòu)造函數(shù)參數(shù)前面添加一個(gè)訪問限定符來聲明
class Person {
    constructor(public name: string){}
}

let p = new Person('小撩');
p.name = '大撩';
console.log(p.name);
console.log(p);

6. 存取器

  1. TypeScript支持通過getter/setters來截取對(duì)對(duì)象成員的訪問
  2. 可以有效地控制對(duì)對(duì)象成員的訪問
注意:
1) >= ES5
2) 如果只實(shí)現(xiàn)了get, 默認(rèn)就是readonly

需求:先檢查密碼是否正確窗价,然后再允許修改員工的信息

// 密碼:
let passCode = 'itLike.com';

class Employee {
    private _fullName: string;
    
    get fullName():string {
        return this._fullName
    }
    
    set fullName(newName:string){
        if(passCode && passCode === 'itLike.com'){
            this._fullName = newName;
        }else{
            console.log("錯(cuò)誤: 沒有權(quán)限修改用戶信息如庭!")
        }
    }
}

let p = new Employee();
p.fullName = '科比';
console.log(p.fullName);

7. 靜態(tài)屬性

  1. 實(shí)例屬性: 類的實(shí)例成員,僅當(dāng)類被實(shí)例化的時(shí)候才會(huì)被初始化的屬性
  2. 我們也可以創(chuàng)建類的靜態(tài)成員撼港,這些屬性存在于類本身而不是類的實(shí)例上面
class Company {
    // 靜態(tài)屬性
    static title = '撩課';
    // 實(shí)例屬性
    constructor(public college: string){};
    // 輸出
    fullName(){
        return Company.title + this.college;
    }
}

let c1 = new Company('web學(xué)院');
console.log(c1.fullName());

let c2 = new Company('Java學(xué)院');
console.log(c2.fullName());

8. 抽象類

抽象類:

1) 抽象類作為其它派生基類使用坪它。
2) 它們一般不會(huì)直接被實(shí)例化。
3) 不同于接口帝牡,抽象類可以包含成員的實(shí)現(xiàn)細(xì)節(jié)往毡。
4) abstract 關(guān)鍵字是用于定義抽象類和在抽象類內(nèi)部定義抽象方法

抽象方法:

1)抽象類中的抽象方法不包含具體實(shí)現(xiàn)并且必須在派生類中實(shí)現(xiàn)
2) 抽象方法的語法與接口方法相似,兩者都是定義方法簽名但不包含方法體
3) 抽象方法必須包含abstract關(guān)鍵字并且可以包含訪問修飾符
abstract class Department {
    name: string;
    constructor(name: string){
        this.name = name;
    }
    printName():void{
        console.log('部門名稱: ' + this.name);
    }
    // 抽象方法
    abstract printMetting():void // 必須在每一個(gè)繼承的派生類中去實(shí)現(xiàn)
}

class AccountingDepartment extends Department {
    constructor(){
        super('財(cái)務(wù)部');
    }
    printMetting(): void {
        console.log('財(cái)務(wù)部每天10:00開會(huì)');
    }
    payPage():void {
        console.log('每天都發(fā)工資');
    }
}

// 約束變量的類型
let department: Department;
// 下面這是錯(cuò)誤的靶溜,抽象類不能直接實(shí)例化
// department = new Department();
department = new AccountingDepartment();
department.printName();
department.printMetting();
department.payPage(); // 錯(cuò)誤: 方法的聲明在抽象類中不存在

9. 把類當(dāng)作接口使用

類定義會(huì)創(chuàng)建兩個(gè)東西卖擅,類的實(shí)例類型和一個(gè)構(gòu)造函數(shù)
因?yàn)轭惪梢詣?chuàng)建出類型,所以能夠在允許使用接口的地方使用類

class Point {
    x: number;
    y: number;
}

interface Point3D extends Point{
    z: number;
}

let point3D: Point3D = {x: 10, y: 20, z: 100};

函數(shù)

1. 基本示例

// 命名函數(shù)
function maxA(x:number, y:number):number{
    return x > y ? x : y;
}

// 匿名函數(shù)
let maxB = function (x:number, y:number):number{
    return x > y ? x : y;
}

// 箭頭函數(shù)
let maxC = (x: number, y: number) => {
    // this
}

let num1:number = 100;
function func(num2, num3):number {
    return num1 + num2 + num3;
}

2. 可選參數(shù)

TypeScript 里的每個(gè)參數(shù)都是必須的
這不是指不能傳遞nullundefined作為參數(shù)墨技,而是說編譯器檢查用戶是否為每個(gè)參數(shù)都傳入了值

不正確的操作

function max(x: number, y: number):number{
    return x > y ? x : y;
}

let res1 = max(10);
let res2 = max(10, 20);

正確的操作

// 可選參數(shù)必須位于必選參數(shù)的后面
function max(x: number, y?: number):number{
    if(y){
        return x > y ? x : y;
    }else {
        return x;
    }
}

let res1 = max(2);
let res2 = max(2, 4);
console.log(res1, res2);

// 可以預(yù)定義一些參數(shù)的值
function func(x: number, y = 4): void {
    console.log(x, y);
}

func(12);
func(2, 1);
func(2, null);

3. 剩余參數(shù)

function sum(x:number, ...resetNumber: number[]):number{
    let result:number = x;
    for(let i = 0; i < resetNumber.length; i++){
        result += resetNumber[i];
    }
    return result;
}

let result = sum(1,2,3,4,5,6);
console.log(result);

泛型

1. 初體驗(yàn)

function getNumber(num: number):number {
    return num;
}

function getNumber(num: any):any {
    return num;
}

getNumber(true);

2. 泛型變量

類型變量:它是一種特殊的變量惩阶,只用于表示類型而不是值

function getNumber<T>(num: T):T {
    return num;
}

let r1 = getNumber<string>('一百萬');
console.log(r1);
let r2 = getNumber<number>(10);
console.log(r2);
// 調(diào)用的時(shí)候,不寫泛型也是可以的扣汪,這個(gè)只是方便人看
let r3 = getNumber(true);
console.log(r3);

擴(kuò)充

function getNumber<T>(num: T):T {
    // 因?yàn)槿绻莕umber類型就沒有l(wèi)ength方法断楷,所以錯(cuò)誤
    console.log(num.length);
    return num;
}

// 這樣就可以啦
function getNumber<T>(num: T[]):T[] {
    console.log(num.length);
    return num;
}

3. 泛型類

class Add<T> {
    zeroValue: T;
    add: (x:T, y:T) => T;
}

// 3.1 number類型
let a = new Add<number>();
a.zeroValue = 100;
a.add(10, 20);

// 3.2 其它類型
let a = new Add<string>(){
    a.zeroValue = '2';
    a.add('200', '100');
}

4. 泛型約束

有時(shí)候我們想去C座某類型的一組值,并且我們知道這組值具有什么樣的屬性
這時(shí)崭别,可以定義一個(gè)接口來描述約束條件

// 創(chuàng)建一個(gè)包含length屬性的接口
// 通過繼承這個(gè)接口冬筒,在函數(shù)調(diào)用的時(shí)候,參數(shù)必須具有l(wèi)ength這個(gè)屬性茅主,object也可以哦
interface LengthWise {
    length: number;
}

function getNum<T extends LengthWise>(num: T):T {
    console.log(num.length);
    return num;
}

console.log(getNum('10'));
console.log(getNum({value:10, length: 20}));

5. 在泛型約束中使用類型參數(shù)

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

let person = {name: '小撩', age: 20, sex: '女'};
// 第二個(gè)參數(shù)舞痰,也就是key,只能是person的三個(gè)key
let p1 = getProperty(person, 'name');
let p2 = getProperty(person, 'age');
let p3 = getProperty(person, 'sex');
console.log(p1);
console.log(p2);
console.log(p3);

類型推斷

1. TypeScript 里诀姚,在有些沒有明確指出類型的地方响牛,類型推斷會(huì)幫助提供類型

let num = 10; // 數(shù)字
let str = '撩課'; // 字符串

2. 最佳通用類型

let arr = [0, 10, true, null] // (number | boolean | null)[]

// 如果是class的話,可能不是我們希望的類型
class Animal {
    breed: string;
}

class Dog extends Animal{};
class Cat extends Animal{};

let zoo = [new Dog(), new Cat()]; // (Dog | Cat)[],而不是我們希望的Animal[]
// 這個(gè)時(shí)候就可以用強(qiáng)制類型
let zoo:Animal[] = [new Dog(), new Cat()];

3. 上下文類型

1)TypeScript類型推斷會(huì)按另外一種方式呀打,我們稱作“上下文類型”
2)上下文類型的出現(xiàn)和表達(dá)式的類型以及所處的位置相關(guān)

window.onmousedown = function(mouseEvent){
    console.log(mouseEvent.target); //OK
    console.log(mouseEvent.liaoke); //不OK
}

上下文類型會(huì)在很多情況下使用到

  1. 通常包含函數(shù)的參數(shù)矢赁,賦值表達(dá)式的右邊,類型斷言贬丛,對(duì)象成員撩银,數(shù)組字面量和返回值語句
  2. 上下文類型也會(huì)作為最佳通用的候選類型
class Animal {
    breed: string;
}

class Dog extends Animal{};
class Cat extends Animal{};

// Animal > Dog > Cat
function createZoo(): Animal[] {
    return [new Dog(), new Cat()];
}

高級(jí)特性

1. 聯(lián)合類型:一個(gè)代碼庫希望傳入多種類型的參數(shù)

/*
    左側(cè)拼接:
    1)如果傳入字符串,則直接拼接
    2)如果傳入數(shù)字豺憔,則創(chuàng)建空格拼接
    3)其它的為非法
*/

// 1. 編譯通過额获,運(yùn)行報(bào)錯(cuò)
function padLeft(value: string, padding: any){
    if(typeof padding === 'number'){
        return Array(padding+1).join(' ') + value;
    }
    if(typeof padding === 'string'){
        return padding + value;
    }
    throw new Error('出現(xiàn)錯(cuò)誤');
}

console.log(padLeft('撩課學(xué)院', 10));
console.log(padLeft('撩課學(xué)院', '3343434343'));
console.log(padLeft('撩課學(xué)院', [21,32,334])); // 編譯通過,運(yùn)行報(bào)錯(cuò)

// 2. 編譯不通過
function padLeft(value: string, padding: string | number){
    if(typeof padding === 'number'){
        return Array(padding+1).join(' ') + value;
    }
    if(typeof padding === 'string'){
        return padding + value;
    }
    throw new Error('出現(xiàn)錯(cuò)誤');
}

console.log(padLeft('撩課學(xué)院', 10));
console.log(padLeft('撩課學(xué)院', '3343434343'));
console.log(padLeft('撩課學(xué)院', [21,32,334])); // 編譯不通過

2. 類型保護(hù)

聯(lián)合類型適用于那些值可以為不同類型的情況
但當(dāng)我們想確切地了解pet是否為Fish或者是Bird時(shí)恭应,怎么辦咪啡?

interface Bird{
    fly();
    sleep();
}

interface Fish{
    swim();
    sleep();
}

function getSmallPet(): Fish | Bird{
    return
}

// 直接寫當(dāng)然是不行的
// let pet = getSmallPet();
// pet.sleep(); // 兩種類型都有sleep方法
// pet.swim(); // Error,比如是Fish類型才可以

// 這樣做暮屡,使用if else也是不行的
// let pet = getSmallPet();
// if(pet.swim){
//  pet.swim();
// }else if(pet.fly){
//  pet.fly();
// }

// 只能通過使用斷言這種方式了
let pet = getSmallPet();
if(pet as Fish){
    (pet as Fish).swim();
}else{
    (pet as Bird).fly();
}

3. 自定義的類型保護(hù)

  1. 類型保護(hù)就是一些表達(dá)式撤摸,它們會(huì)在運(yùn)行時(shí)檢查以確保在某個(gè)作用域里的類型
  2. 定義一個(gè)類型保護(hù),我們只要簡單地定義一個(gè)函數(shù)褒纲,它的返回值是一個(gè)類型謂詞
interface Bird{
    fly();
    sleep();
}

interface Fish{
    swim();
    sleep();
}

function getSmallPet(): Fish | Bird{
    return
}

// 謂詞:p is type
function isFish(pet:Fish | Bird): pet is Fish{
    return (pet as Fish).swim !== undefined;
}

let pet = getSmallPet();
if(isFish){
    pet.swim();
}else{
    pet.fly();
}

4. instanceof 類型保護(hù)

instanceof 類型保護(hù)是通過構(gòu)造函數(shù)來細(xì)化類型的一種方式

class Bird{
    fly(){
        console.log('鳥在飛');
    };
    sleep(){
        console.log('鳥在睡');
    };
}

class Fish{
    swim(){
        console.log('魚在游');
    };
    sleep(){
        console.log('魚在睡');
    };
}

function getSmallPet(){
    return Math.random() > 0.5 ? new Bird() : new Fish();
}

let pet = getSmallPet();
if(pet instanceof Bird){
    pet.fly();
}

if(pet instanceof Fish){
    pet.swim();
}

5. 可以為null的類型

  1. TypeScript具有兩種特殊的類型准夷, null和undefined,他們分別具有值null和undefined
  2. 默認(rèn)情況下莺掠,類型檢查器認(rèn)為null與undefined可以賦值給任何類型
  3. 這就意味著:null和undefined是所有其它類型的一個(gè)有效值衫嵌,這也意味著,你阻止不了
    將它們賦值給其它類型彻秆,就算是你想要阻止這種情況也不行楔绞。null的發(fā)明者,Tony Hoare唇兑,稱
    它為價(jià)值億萬美金的錯(cuò)誤

--strictNullChecks標(biāo)記可以解決此錯(cuò)誤:當(dāng)你聲明一個(gè)變量時(shí)酒朵,它不會(huì)自動(dòng)包含null或undefined

let s = '撩課';
s = null; // 錯(cuò)誤
console.log(s);
let s1:string | null = 'bar';
s1 = null;
console.log(s1);
s1 = undefined; // 錯(cuò)誤
console.log(s1);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市扎附,隨后出現(xiàn)的幾起案子蔫耽,更是在濱河造成了極大的恐慌,老刑警劉巖留夜,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匙铡,死亡現(xiàn)場離奇詭異,居然都是意外死亡碍粥,警方通過查閱死者的電腦和手機(jī)鳖眼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嚼摩,“玉大人钦讳,你說我怎么就攤上這事矿瘦。” “怎么了蜂厅?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵匪凡,是天一觀的道長膊畴。 經(jīng)常有香客問我掘猿,道長,這世上最難降的妖魔是什么唇跨? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任稠通,我火速辦了婚禮,結(jié)果婚禮上买猖,老公的妹妹穿的比我還像新娘改橘。我一直安慰自己,他們只是感情好玉控,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布飞主。 她就那樣靜靜地躺著,像睡著了一般高诺。 火紅的嫁衣襯著肌膚如雪碌识。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天虱而,我揣著相機(jī)與錄音筏餐,去河邊找鬼。 笑死牡拇,一個(gè)胖子當(dāng)著我的面吹牛魁瞪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惠呼,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼导俘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了剔蹋?” 一聲冷哼從身側(cè)響起趟畏,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎滩租,沒想到半個(gè)月后赋秀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡律想,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年猎莲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片技即。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡著洼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情身笤,我是刑警寧澤豹悬,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站液荸,受9級(jí)特大地震影響瞻佛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜娇钱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一伤柄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧文搂,春花似錦适刀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至硝皂,卻和暖如春常挚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吧彪。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國打工待侵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姨裸。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓秧倾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親傀缩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子那先,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361