TypeScript笔记(2)

元组

在TypeScript中,有元组的概念,这个概念的js实现是数组,所以可以理解为是有不同类型对象的数组。

let a:[number,string];
a = [55,'25']

这样是元组的基本用法,有基本用法,那就一定有奇怪的用法。

我们可以通过一定方法对任意一个进行赋值,而不管另一个

let a:[number,string];
a[1] = '25'

但是我们不可以在对a直接赋值的时候,给出不符合规则的值

let a:[number,string] = 55;

这样是无法通过编译的。

既然是数组了,那么可不可以继续添加对象进去呢?当然是可以的,但是需要是规定的类型才行,比如上面我们规定元组的第一个元素是number类型,第二个是string类型,那么后续的只能是number、string或者他们的子类型。

字符串字面量类型和枚举类型

这两个为什么要放到一起说呢?因为他们都限定了在这个类型内,可以选择的字符串只有有限个,所以两个放到一起说一下。

字符串字面量类型

这个类型特别简单,就是在自己设定的类型中,只有有自己设定的值。

type Name = 'xiaoming' | 'xiaohong' | 'xiaoliang';
function call(name: Name){
    //call
}

call('xiaoming'); //可以编译
call('wo'); //不能编译

这就是字符串字面量类型,没有任何变化。

枚举

枚举类型被用于取值限定在一定范围内的场景,用途类似上面的字符串字面量类型。

enum Week {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

console.log(Days["Sun"] === 0); // true
console.log(Days[0] === "Sun"); // true

这样就是一个枚举类型了,他在js的实现是

var Week;
(function (Week) {
    Week[Week["Sun"] = 0] = "Sun";
    Week[Week["Mon"] = 1] = "Mon";
    Week[Week["Tue"] = 2] = "Tue";
    Week[Week["Wed"] = 3] = "Wed";
    Week[Week["Thu"] = 4] = "Thu";
    Week[Week["Fri"] = 5] = "Fri";
    Week[Week["Sat"] = 6] = "Sat";
})(Week || (Week = {}));

这个实现没什么好说的,看一眼应该就知道他的原理是怎么回事了,如果觉得有点抽象,可以再浏览器里打印一下Week这个对象,就明白这里的枚举类型是什么意思了。

枚举类型还可以手动赋值

enum Week {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 7); // true
console.log(Days["Tue"] === 2); // true

枚举类型的需要会按照以最后一个设定值为基础,每一个值+1的顺序往下排,即使最后一个设定值不为整数也是一样。

还可以用断言添加非数值的序数,但是这个断言后面的所有序数都要手动设置了。

enum Days {Sun = 7, Mon, Tue, Wed, Thu, Fri, Sat = <any>"a"};

除了固定值的序号,还可以用计算量做需要,但是计算量和字符串序号一样,后面都不能有未设定序号了。

在es6之前,JavaScript没有类的概念,但是在es6中,出现了类,同样TypeScript中也有对类的规定,这里的规定很像java中类的规则。

修饰符

TypeScript中有三个修饰符,分别是public,private,protected。

public是公开的,可任意访问的,

private是私有的,只能在类内部访问,他的子类和外部是不能访问的。

protected是受保护的,同样不能再外部访问,但是可以再子类和内部访问。

class Animal {
    public name;
    public constructor(name) {
        this.name = name;
    }
}
let a = new Animal('Cat');
console.log(a.name); // Cat

这样的访问是没有问题的

class Animal {
    private name;
    public constructor(name) {
        this.name = name;
    }
}
let a = new Animal('Cat');
console.log(a.name);

这样编译就会报错,因为私有属性是不可以在外部被访问的。

class Animal {
    protected name;
    public constructor(name) {
        this.name = name;
    }
}

class Cat extends Animal {
    constructor(name) {
        super(name);
        console.log(this.name);
    }
}

受保护的属性是可以再子类中被访问,但是不能在外部访问。

抽象类

所谓抽象类,就是不能实例化的类,这种类就是为了子类而存在的,他们的子类可以实例化。

抽象类还有抽象方法,抽象方法可以再抽象类中定义,不去做实现,在子类中必须实现抽象方法。关键字是abstract

abstract class Animal {
    public name;
    public constructor(name) {
        this.name = name;
    }
    public abstract sayHi();
}

class Cat extends Animal {
    public eat() {
        console.log(`${this.name} is eating.`);
    }
}

let cat = new Cat('Tom');

这样会报错,因为还有一个抽象方法没有写实现。

类与接口

接口的实质是对象的形状,那么接口可以规定对象,可以规定类吗?

答案是啊可以的

interface Alarm {
    alert();
}

class Door {
}

class SecurityDoor extends Door implements Alarm {
    alert() {
        console.log('SecurityDoor alert');
    }
}

class Car implements Alarm {
    alert() {
        console.log('Car alert');
    }
}

这里抽象出来一个接口,叫做警铃。门有门铃功能,车有警铃功能,那么把这两个类共有的东西抽象出来,就是类的接口。

接口规定,这个类必须有这个属性,至于能不能有其他的东西,接口不管。如果类可以抽象出来多个接口,那么也可以使用多个接口规定同一个类

interface Alarm {
    alert();
}

interface Light {
    lightOn();
    lightOff();
}

class Car implements Alarm, Light {
    alert() {
        console.log('Car alert');
    }
    lightOn() {
        console.log('Car light on');
    }
    lightOff() {
        console.log('Car light off');
    }
}

接口还有一种很特殊的继承性,子接口可以继承父接口的规则。

interface Alarm {
    alert();
}

interface LightableAlarm extends Alarm {
    lightOn();
    lightOff();
}

个人不是很喜欢这种继承,确实可以再项目扩大之后,写的更加简略比如上面的

class Car implements Alarm, Light {
    alert() {
        console.log('Car alert');
    }
    lightOn() {
        console.log('Car light on');
    }
    lightOff() {
        console.log('Car light off');
    }
}

此时可以简写为

class Car implements Light {
    alert() {
        console.log('Car alert');
    }
    lightOn() {
        console.log('Car light on');
    }
    lightOff() {
        console.log('Car light off');
    }
}

但是这时如果Light是多层的嵌套的时候,你就会很疑惑他的规则到底是什么。想要查清楚需要追溯到最上面一层,就好像一个树,你得看完他所有节点才能清楚的知道全部,对于ts的检查来说自然无所谓,但是对于写代码的人来说,就很烦,尤其是在没有完善的文档的情况下。

接口还可以直接从类里继承

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

interface Point3d extends Point {
    z: number;
}

let point3d: Point3d = {x: 1, y: 2, z: 3};

对这种东西,个人表示也不太喜欢,理由基本同上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值