TypeScript

布尔值 boolean

 

let isDone: boolean = false;

注意,使用构造函数 Boolean 创造的对象不是布尔值

 

let newBool: boolean = new Boolean(true);
// 编译报错: 不能将类型“Boolean”分配给类型“boolean”。“boolean”是基元,但“Boolean”是包装器对象。如可能首选使用“boolean”。ts(2322)

数字 number

 

let number: number = 6;
let notANumber: number = NaN;

字符串 string

 

let  string: string = 'Tom';
let sentence: string = `my name is ${aString}`;

空值 void

void 类型的变量只能赋值为 undefined 和 null

 

let unusable: void = undefined;

可以用 void 表示没有任何返回值的函数

 

function alertName(): void {
  alert('My name is Tom');
}

null 和 undefined

undefined 类型的变量只能被赋值为 undefined,null 类型的变量只能被赋值为 null

 

let u: undefined = undefined;
let n: null = null;

与 void 的区别是,undefined 和 null 是所有类型的子类型。也就是说 undefined 类型的变量,可以赋值给 number 类型的变量:

 

let u: undefined;
let num: number = u;
let num2:number = undefined;
// 编译合法 undefined是number的子类型

let unm2: void;
let num3: number = unm2;
// => 不合法 (void不是number的子类型)

任意值 any

any 用来表示允许赋值为任意类型

 

let anyType:any = 'seven';
anyType = 7;

在任意值上访问任何属性和方法都是允许的,即不做类型检查

 

let anyType:any = 'seven';
console.log(anyType.name().age) 
// => 允许编译,但是js执行会报错

变量如果在声明的时候,未指定其类型, 也没有赋值, 那么它会被推断(类型推论)为任意值类型而完全不被类型检查

 

let something; 
// 等价于 let something: any;
something = 'seven';
something = 7;

数组

可理解为相同类型的一组数据,数组类型有多种定义方式

1,类型 + 方括号( type [ ] )

这种方式定义的数组项中不允许出现其他的类型

 

let list: number[] = [1, 2, 3];

2,数组泛型 Array < type >

 

let list: Array<number> = [1, 2, 3];

枚举 enum

['enəm]

枚举类型用于取值被限定在一定范围内的场景,如一周只有7天,一年只有4季等。

枚举初始化

枚举初始化可以理解为给枚举成员赋值。每个枚举成员都需要带有一个值,在未赋值的情况下, 枚举成员会被赋值为从 0 开始, 步长为 1 递增的数字:

 

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

console.log(Weeks['Mon']); // => 0
console.log(Weeks[0]); // => 'Mon'
console.log(Weeks.Tue); // => 1

手动赋值时, 未赋值的枚举成员会接着上一个枚举项递增(初始化):

 

enum Weeks {
    Mon, Tue, Wed, Thu = 2, Fri, Sat = -1.5, Sun
};

console.log(Weeks['Mon']); // => 0
console.log(Weeks.Wed); // => 2
console.log(Weeks.Thu); // => 2
console.log(Weeks.Fri); // => 3
console.log(Weeks.Sun); // => -0.5

上例中,未手动赋值的 Wed 和手动赋值的 Thu 取值重复了,但是 TypeScript 并不会报错,该种情况可能会引起取值错误,所以使用的时候最好避免出现取值重复的情况。

TypeScript 支持 数字 的和基于字符串的枚举。

数字枚举

 

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

字符串枚举

 

enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}

接口 Interfaces

接口(Interfaces)是一个很重要的概念,可以理解为一种规范或者约束,用来描述 对象(object) 的形状 或者对 类(class) 的行为 进行抽象。对类的行为抽象将在后面 类与接口 一章中介绍,下面主要介绍对对象的形状进行描述。

接口定义

使用 interface 定义接口, 接口名称一般首字母大写,定义接口的时候,只定义声明即可,不包含具体内容:

 

// 定义一个接口 Person
interface Person {
  name: string;
  age: number;
}

// 定义一个个变量,它的类型是 Person
let tom: Person = {
  name: 'Tom',
  age: 25
};

实现接口的时候,要实现里面的内容,定义的变量比接口少了或多了属性都是不允许的:

 

let tom: Person = {
  name: 'tom'
}
// => 编译报错,少了age属性

可选属性

使用 ? 代表可选属性, 即该属性可以不存在, 但不允许添加未定义的属性

 

interface Person {
  name: string;
  age?: number;
}
let tom: Person = {
  name: 'tom'
}
// age是可选属性

任意属性

定义了任意属性后可以添加未定义的属性,并可以指定属性值的类型

 

interface Person03 {
  name: string;
  age?: number;
  [propName: string]: any;
}
let tom04: Person03 = {
  name: 'Tom',
  age: 25,
  gender: 'male'
};

定义了任意属性,那么确定属性和可选属性都必须是它的子属性

 

interface Person {
  name: string;
  age?: number;
  [propName: string]: string;
}
// 编译报错:Person定义了一个任意属性,其值为string类型。则Person的所有属性都必须为string类型,而age为number类型

只读属性 readonly

 

interface Person {
  readonly id: number;
  name: string;
  age?: number;
  [propName: string]: any;
}

只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候

 

let person: Person = {
  id: 100,
  name: 'tom',
}
person05.id = 90;
// => 编译报错:id为只读, 不可修改

let person2: Person = {
  name: 'welson',
  age: 2
}
// => 编译报错:给对象 person2 赋值,未定义只读属性id
person2.id = 1;
// => 编译报错:id为只读, 不可修改

函数类型接口

 

// 只有参数列表和返回值类型的函数定义, 参数列表里的每个参数都需要名字和类型
interface SearchFunc {
  (source: string, subString: string): boolean;
}

函数

函数声明

 

function sum(x: number, y: number): number {
    return x + y;
}

输入多余的(或者少于要求的)参数,是不被允许的

 

sum(1, 2, 3);
// 编译报错:多了1个参数

匿名函数(函数表达式)

 

let mySum = function (x: number, y: number): number {
    return x + y;
};

上面的代码只对等号右侧的匿名函数进行了类型定义,而等号左边的 mySum,是通过赋值操作进行类型推论而推断出来的。如果需要我们手动给 mySum 添加类型,则应该是这样:

 

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};
// 注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>

用接口定义函数的形状

 

interface FuncAdd {
  (value: number, increment: number): number
}
let add: FuncAdd;
add = function(value: number, increment: number): number {
  return value + increment;
}
// 函数的参数名不需要与接口里定义的名字相匹配
let add2: FuncAdd;
add2 = function(a: number, b: number) {
  return a + b;
}

可选参数

可选参数必须接在必需参数后面,换句话说,可选参数后面不允许再出现必须参数了

 

function addNum(a: number, b: number, c? :number): number {
    if(c) {
        return a + b + c;
    } else {
        return a + b;
    }
}
console.log(add(1, 2));

默认参数

类比 ES6 中的默认值

 

function add(a: number = 1, b: number): number {
    return a + b;
}
console.log(add(undefined, 1));

剩余参数

类比 Es6 中对象展开

 

interface AddFunc {
  (num1: number, ...rest: number[]): number
}
let add: AddFunc;
add = function(a: number, ...rest: number[]): number {
    let result = a; 
    rest.map(v => result += v);
    return result;
}
console.log(add(1,2,3,4));

类 class

同ES6 的 class

相关概念

  • 类(Class):定义了一件事物的抽象特点,包含它的属性和方法
  • 对象(Object):类的实例,通过 new 生成
  • 面向对象(OOP)的三大特性:封装、继承、多态
  • 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据
  • 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性
  • 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 CatDog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat
  • 存取器(getter & setter):用以改变属性的读取和赋值行为
  • 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法
  • 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
  • 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口

类的定义

使用 class 定义类,使用 constructor 定义构造函数。

通过 new 生成新实例的时候,会自动调用构造函数。

 

class Animal {
        name:string; // 定义属性
    constructor(name) {
        this.name = name; // 属性赋值
    }
    sayHi() {
        return `我叫 ${this.name}`;
    }
}

let cat = new Animal('Tom');
console.log(cat.sayHi()); // 我叫 Tom

类的继承

使用 extends 关键字实现继承,子类中使用 super 关键字来调用父类的构造函数和方法。

 

class Cat extends Animal {
    color: string;
    constructor(name, color) {
        super(name); // 调用父类Animal的 constructor(name)
        this.color = color
    }
    sayHi() {
        // 调用父类的 sayHi();
        return super.sayHi() + '我是一只'+ this.color + ' 色的猫,'; 
    }
}

let c = new Cat('Tom', '橘黄'); // Tom
console.log(c.sayHi()); // 我叫 Tom,我是一只橘黄色的猫;

let cat2 = new Cat('Jerry');
cat2.color = '黑';
console.log(c.sayHi()); // 我叫 Jerry,我是一只黑色的猫;

存取器

使用 getter 和 setter 可以改变属性的赋值和读取行为:

 

class Animal {
        name:string;
    constructor(name) {
        this.name = name;
    }
    get name() {
        return 'Jack';
    }
    set name(value) {
        console.log('setter: ' + value);
    }
}

let a = new Animal('Kitty'); // setter: Kitty
a.name = 'Tom'; // setter: Tom
console.log(a.name); // Jack

实例属性和方法

js中的属性和方法:

 

// js中
function Person(name) {
  this.name = name; // 实例属性
  this.eat = function(){ console.log('eat') };  // 实例方法
}
Person.age = 19; // 静态属性
Person.sleep = function(){ console.log('sleep') }; // 静态方法

// 访问实例方法和属性:
var tom = new Person('tom');
console.log(tom.name) // tom
tom.eat();
tom.sleep() // error: tom.sleep is not a function

// 访问静态方法和属性:
console.log(Person.age); // 19
Person.sleep();
Person.eat(); // error: Person.eat is not a function

ES6 中实例的属性只能通过构造函数中的 this.xxx 来定义:

 

class Animal {
    constructor(){
            this.name = 'tom';
        }
    eat() {}
}

let a = new Animal();
console.log(a.name); // tom

ES7 提案中可以直接在类里面定义:

 

// ts
class Animal {
    name = 'tom';
    eat() {}
}

let a = new Animal();
console.log(a.name); // Jack

静态属性和方法

ES7 提案中,可以使用 static 定义一个静态属性或方法。静态方法不需要实例化,而是直接通过类来调用:

 

// ts
class Animal {
    static num = 42;
    static isAnimal(a) {
        return a instanceof Animal;
    }
}

console.log(Animal.num); // 42
let a = new Animal('Jack');
Animal.isAnimal(a); // true
a.isAnimal(a); // TypeError: a.isAnimal is not a function

访问修饰符

public

公有属性或方法,可以在任何地方被访问到,默认所有的属性和方法都是 public

private

私有属性或方法,不能在声明它的类的外部访问,也不可以在子类中访问

protected

受保护的属性或方法,它和 private 类似,区别是它可以在子类中访问

 

class Person {
    public name:string;
    private idCard:number;
    protected phone:number;
    constructor(name,idCard,phone) {
        this.name = name;
        this.idCard = idCard;
        this.phone = phone;
    }
}

let tom = new Person('tom',420000,13811110000);
console.log(tom.name) // tom

console.log(tom.idCard) 
// error:Property 'idCard' is private and only accessible within class 'Person'.

console.log(tom.phone)
// error:Property 'phone' is protected and only accessible within class 'Person' and its subclasses

class Teacher extends Person {
    constructor(name,idCard,phone) {
        super(name,idCard,phone);
        console.log(this.name)
        console.log(this.phone)
                console.log(this.idCard)
                // error:Property 'idCard' is private and only accessible within class 'Person'.
    }
}


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值