TypeScript-2

二、进阶

1.类型别名

类型别名用来给一个类型起个新名字。

type name=string;
type nameFn=()=>string;

function test(n:name|nameFn):name{
    if(typeof n=='string'){
        return n;
    }else{
        return n();
    }
}

2.字符串字面量类型

用来约束取值只能是某几个字符串中的一个。

类型别名与字符串字面量类型都是使用 type 进行定义。

type EventNames='click'|'scroll'|'mousemove';
function handleEvent(el:Element,event:EventNames){

}
handleEvent(document.body,'scroll');
handleEvent(document.body,'dbclick');//error : Argument of type '"dbclick"' is not assignable to parameter of type 'EventNames'.

3.元组

数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象。

let list:[string,number]=['aa',2];

// 当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项。
 let list1:[string,number]=['aa'];//error:Type '[string]' is not assignable to type '[string, number]'.
 

 

4.枚举

枚举(Enum)类型用于取值被限定在一定范围内的场景

// 枚举使用 enum 关键字来定义
// 枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:

enum color {red,green,blue};
console.log(color[0],color[1],color[2]);//red green blue
console.log(color['red'],color['green'],color['blue']);//0 1 2

// 1.手动赋值

// 手动赋值的枚举项也可以为小数或负数,不是数字,此时后续未手动赋值的项的递增步长仍为 1

enum color {red=1.5,green,blue='a'};

console.log(color['red'],color['green'],color['blue']);//1.5 2.5 "a"

// 2. 常数项和计算所得项

// 计算所得项
enum color {red,green,blue="blue".length};
console.log(color['red'],color['green'],color['blue']);//0 1 4

// 如果紧接在计算所得项后面的是未手动赋值的项,那么它就会因为无法获得初始值而报错:
// enum Color {Red = "red".length, Green, Blue};//error: Enum member must have initializer

// 3.常数枚举 const
// 不能包含计算成员
const enum color {red,green,blue};
console.log(color['red'],color['green'],color['blue']);//0 1 2

// 4.外部枚举
// 使用 declare enum 定义的枚举类型
// 外部枚举与声明语句一样,常出现在声明文件中。

declare enum color {red,green,blue};
console.log(color['red'],color['green'],color['blue']);//0 1 2

 5.类

// 1.public private 和 protected
// public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
// private 修饰的属性或方法是私有的,不能在声明它的类的外部访问,在子类中也是不允许访问的
// protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的

// ++++++private++++++
class Animal{
    private name;
    public constructor(name){
        this.name=name;
    }
}

class Cat extends Animal{
    constructor(name){
        super(name);
        console.log(this.name);//error: Property 'name' is private and only accessible within class 'Animal'.
    }
}

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

class Cat extends Animal{
    constructor(name){
        super(name);
        console.log(this.name);//可以在子类中访问
    }
}
let a=new Cat('ass');
console.log(a.name);//error:外部不可以访问

// 2.抽象类
// abstract 用于定义抽象类和其中的抽象方法。

// 抽象类是不允许被实例化的:
// 抽象类中的抽象方法必须被子类实现:

abstract class Animal{
    public name;
    constructor(name){
        this.name=name;
    }
    public abstract say();//抽象类中的抽象方法必须被子类实现:
}
// 抽象类是不允许被实例化的:
let a=new Animal('aa');//error: Cannot create an instance of the abstract class 'Animal'.

class Cat extends Animal{
    say(){
        console.log(`${this.name}++++++`);
    }
}

let b=new Cat('suaa');
b.say();

// 3.类的类型

class Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    sayHi(): string {
      return `My name is ${this.name}`;
    }
}

let a: Animal = new Animal('Jack');
console.log(a.sayHi()); // My name is Jack

 

 

6.类与接口

 

//1. 类实现接口
//有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现。 

// 一个类可以实现多个接口:
interface eat{
    food();
}
interface go{
    run();
}
class Person implements eat,go{
    food(){
        console.log('apple');
    }
    run(){
        console.log('fast');
    }
}

// 2.接口继承接口

interface go{
    run();
}
interface eat extends go{
    food();
}

class Person implements eat{
    food(){
    }
    run(){
    }
}

// 3.接口继承类

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

interface Point3d extends Point{
    z:number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};

 

7.泛型

泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候在指定类型

 

// 在函数名后添加了 <T>,其中 T 用来指代任意输入的类型,在后面的输入 value: T 和输出 Array<T> 中即可使用了
function test<T>(len:number,value:T):Array<T>{
    let res:T[]=[];
    for(let i=0;i<len;i++){
        res[i]=value;
    }
    return res;
}
console.log(test(3,'a+'));//["a+", "a+", "a+"]

// 1.多个类型参数
// 定义泛型的时候,可以一次定义多个类型参数:

function test<T,U>(arr:[T,U]):[U,T]{
    return [arr[1],arr[0]]
}
console.log(test([1,'a']));//["a", 1]

// 2.泛型约束
// 可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量

interface lengthWise{
    length:number;
}

function getLen<T extends lengthWise>(param:T):T{
    console.log(param.length);
    return param;
}
getLen(7);// error TS2345: Argument of type '7' is not assignable to parameter of type 'Lengthwise'.
getLen('aaa');


// 多个类型参数之间也可以互相约束:
function test<T extends U,U>(target:T,source:U):T{
    for(let id in source){
        target[id]=(<T>source)[id];
    }
    return target;
}
let b=test({ a: 1, b: 2, c: 3, d: 4 }, { b: 10, d: 20 });
console.log(b);//{a: 1, b: 10, c: 3, d: 20}

// 3.泛型接口

interface CreateArrayFunc<T> {
    (length: number, value: T): Array<T>;
}

let createArray: CreateArrayFunc<any>;
createArray = function<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}

createArray(3, 'x'); // ['x', 'x', 'x']

// 4.泛型类

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

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };


// 5.泛型参数的默认类型

function createArray<T = string>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}

 

 

8.声明合并

如果定义了两个相同名字的函数,接口或类,那么它们会合并成一个类型

// 1.函数的合并

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

// 2. 接口的合并
// 接口的属性在合并时会简单的合并到一个接口中
// 合并的属性的类型必须是唯一的:
interface test{
    name:string;
}
interface test{
    name:string;//类型需要一致
    age:number;
}
// 等价于
interface test{
    name:string;
    age:number;
}
// 3.类的合并与接口合并一致

 

 

posted @ 2018-11-19 15:51  yuesu  阅读(230)  评论(0编辑  收藏  举报