一 , 交叉类型(操作符 & ):

代码 :

function extend<T, U>(first: T, second: U): T & U {
    let result = <T & U>{};
    for (let id in first) {
        (<any>result)[id] = (<any>first)[id];
    }
    for (let id in second) {
        if (!result.hasOwnProperty(id)) {
            (<any>result)[id] = (<any>second)[id];
        }
    }
    return result;
}

class Person {
    constructor(public name: string) { }
}
interface Loggable {
    log(): void;
}
class ConsoleLogger implements Loggable {
    log() {
        console.log(`AAAAA`);
    }
}
let jim = extend(new Person("Jim"), new ConsoleLogger());
let n = jim.name;
console.log(`this is name : ${n}`);
jim.log();

编译及结果:

可以看出jim既有Person的成员 , 也有ConsolerLogger的成员 . 交叉类型既是将此2种类型合并在一起使用:编译成的JS如下:

function extend(first, second) {
    var result = {};
    for (var id in first) {
        result[id] = first[id];
    }
    for (var id in second) {
        if (!result.hasOwnProperty(id)) {
            result[id] = second[id];
        }
    }
    return result;
}
var Person = (function () {
    function Person(name) {
        this.name = name;
    }
    return Person;
}());
var ConsoleLogger = (function () {
    function ConsoleLogger() {
    }
    ConsoleLogger.prototype.log = function () {
        console.log("AAAAA");
    };
    return ConsoleLogger;
}());
var jim = extend(new Person("Jim"), new ConsoleLogger());
var n = jim.name;
console.log("this is name : " + n);
jim.log();


二,联合类型(操作符 | )

abstract class Monster{
    public tpid : number;
    public name : string;
    public abstract attack:()=>string;

    constructor( tpid : number , name : string ){
        this.tpid = tpid;
        this.name = name;
    }
}
class Godzilla extends Monster{
    constructor(tpid : number){
        super( tpid , `Godzilla` );
    }
    //实现attack方法
    public attack:()=>string=function(){
        return `id : ${this.tpid} ,name : ${this.name} -> can fire`;
    }
}
class Medusa extends Monster{
    constructor(tpid : number){
        super(tpid,`Medusa`);
    }
    public attack:()=>string=function(){
        return `id : ${this.tpid}  , name : ${this.name} -> can turn to stone`;
    }
}


enum Monster_Type{
    Godzilla = 0,//哥斯拉
    Medusa = 1,//美杜莎
}
//!important
//使用联合类型
//因为返回参数可能是哥斯拉 也可能是美杜莎 所以使用联合类型(多选一)
let create_monster : ( type : Monster_Type , tpid : number ) => Godzilla | Medusa = function( ty , id ){
    switch ( ty ){
        case Monster_Type.Godzilla:
            return new Godzilla(id);
        case Monster_Type.Medusa:
            return new Medusa(id);
    }
    return null;
};

let gsl : Godzilla = create_monster( Monster_Type.Godzilla , 1 );
console.log( `gsl :: ${gsl.attack()}` );

let mds : Medusa = create_monster( Monster_Type.Medusa , 2 );
console.log( `mds :: ${mds.attack()}` );

上述代码 : create_monster方法的返回类型使用了联合类型

得到结果:

做一个测试 , 如果联合参数列表中没有AA类型 , 如果我们强制返回AA:

abstract class Monster{
    public tpid : number;
    public name : string;
    public abstract attack:()=>string;

    constructor( tpid : number , name : string ){
        this.tpid = tpid;
        this.name = name;
    }
}
class Godzilla extends Monster{
    constructor(tpid : number){
        super( tpid , `Godzilla` );
    }
    //实现attack方法
    public attack:()=>string=function(){
        return `id : ${this.tpid} ,name : ${this.name} -> can fire`;
    }
}
class Medusa extends Monster{
    constructor(tpid : number){
        super(tpid,`Medusa`);
    }
    public attack:()=>string=function(){
        return `id : ${this.tpid}  , name : ${this.name} -> can turn to stone`;
    }
}

class AA{

}

enum Monster_Type{
    Godzilla = 0,//哥斯拉
    Medusa = 1,//美杜莎
    AA = 2
}
//使用联合类型(AA并没有被加入到联合类型 (返回类型中)) Error
//因为返回参数可能是哥斯拉 也可能是美杜莎 所以使用联合类型(多选一)
let create_monster : ( type : Monster_Type , tpid : number ) => Godzilla | Medusa = function( ty , id ){
    switch ( ty ){
        case Monster_Type.Godzilla:
            return new Godzilla(id);
        case Monster_Type.Medusa:
            return new Medusa(id);
        case Monster_Type.AA:
            return new AA();
    }
    return null;
};

let gsl : Godzilla = create_monster( Monster_Type.Godzilla , 1 );
console.log( `gsl :: ${gsl.attack()}` );

let mds : Medusa = create_monster( Monster_Type.Medusa , 2 );
console.log( `mds :: ${mds.attack()}` );

编译报错:


这里需要注意一点 : 代码如下

abstract class Monster{
    public tpid : number;
    public name : string;
    public abstract attack:()=>string;

    constructor( tpid : number , name : string ){
        this.tpid = tpid;
        this.name = name;
    }
}
/**
 * 哥斯拉
 */
class Godzilla extends Monster{

    constructor(tpid : number){
        super( tpid , `Godzilla` );
    }
    //实现attack方法
    public attack:()=>string=function(){
        return `id : ${this.tpid} ,name : ${this.name} -> can fire`;
    }
    //实现喷火技能
    public fire:()=>string=function(){
        return `i can breathe fire`;
    }
}
/**
 * 美杜莎
 */
class Medusa extends Monster{
    constructor(tpid : number){
        super(tpid,`Medusa`);
    }
    //实现attack方法
    public attack:()=>string=function(){
        return `id : ${this.tpid}  , name : ${this.name} -> can turn to stone`;
    }
    //实现石化技能
    public stone:()=>string=function(){
        return `I can turn you into a stone`;
    }
}

/**
 * 怪物类型枚举
 */
enum Monster_Type{
    Godzilla = 0,//哥斯拉
    Medusa = 1//美杜莎
}

//使用联合类型
//因为返回参数可能是哥斯拉 也可能是美杜莎 所以使用联合类型(多选一)
let create_monster : ( type : Monster_Type , tpid : number ) => Godzilla | Medusa = function( ty , id ){
    switch ( ty ){
        case Monster_Type.Godzilla:
            return new Godzilla(id);
        case Monster_Type.Medusa:
            return new Medusa(id);
    }
    return null;
};

/*
 function create_monster( type : Monster_Type , tpid : number ) : Godzilla | Medusa{
 switch ( type ){
 case Monster_Type.Godzilla:
 return new Godzilla(tpid);
 case Monster_Type.Medusa:
 return new Medusa(tpid);
 }
 return null;
 }
 */

let gsl  = create_monster( Monster_Type.Godzilla , 1 );
console.log( `gsl :: ${gsl.attack()}` );

let mds : Medusa  = create_monster( Monster_Type.Medusa , 2 );
console.log( `mds :: ${mds.attack()}` );

编译报错如下:


解决方案有2种 :

① , 将 ":Medusa"去掉(如上图) , 因为Godzilla类和Medusa类不兼容 . 而返回类型使用了联合类型.如果有"Medusa" ,他会检测 Godzilla类和Medusa类的兼容性而报错.

② , 将Godzilla类里面的方法fire 及 Medusa里面的方法stone去掉,以使他们兼容 . 这时可以将":Medusa"加上.


三,保护类型

abstract class Monster{
    public tpid : number;
    public name : string;
    public abstract attack:()=>string;

    constructor( tpid : number , name : string ){
        this.tpid = tpid;
        this.name = name;
    }
}
/**
 * 哥斯拉
 */
class Godzilla extends Monster{

    constructor(tpid : number){
        super( tpid , `Godzilla` );
    }
    //实现attack方法
    public attack:()=>string=function(){
        return `id : ${this.tpid} ,name : ${this.name} -> can fire`;
    }
    //实现喷火技能
    public fire:()=>string=function(){
        return `i can breathe fire`;
    }
}
/**
 * 美杜莎
 */
class Medusa extends Monster{
    constructor(tpid : number){
        super(tpid,`Medusa`);
    }
    //实现attack方法
    public attack:()=>string=function(){
        return `id : ${this.tpid}  , name : ${this.name} -> can turn to stone`;
    }
    //实现石化技能
    public stone:()=>string=function(){
        return `I can turn you into a stone`;
    }
}

/**
 * 怪物类型枚举
 */
enum Monster_Type{
    Godzilla = 0,//哥斯拉
    Medusa = 1//美杜莎
}

//使用联合类型
//因为返回参数可能是哥斯拉 也可能是美杜莎 所以使用联合类型(多选一)
let create_monster : ( type : Monster_Type , tpid : number ) => Godzilla | Medusa = function( ty , id ){
    switch ( ty ){
        case Monster_Type.Godzilla:
            return new Godzilla(id);
        case Monster_Type.Medusa:
            return new Medusa(id);
    }
    return null;
};

/*
 function create_monster( type : Monster_Type , tpid : number ) : Godzilla | Medusa{
 switch ( type ){
 case Monster_Type.Godzilla:
 return new Godzilla(tpid);
 case Monster_Type.Medusa:
 return new Medusa(tpid);
 }
 return null;
 }
 */

let gsl  = create_monster( Monster_Type.Godzilla , 1 );
//console.log( `gsl :: ${gsl.attack()}` );
//
let mds  = create_monster( Monster_Type.Medusa , 2 );
//console.log( `mds :: ${mds.attack()}` );

console.log((<Godzilla>gsl).fire());//(<Godzilla>gsl).fire
console.log((<Medusa>mds).stone());

结果:

如上述代码 :

let gsl  = create_monster( Monster_Type.Godzilla , 1 );

let mds  = create_monster( Monster_Type.Medusa , 2 );

gsl 及 mds 都没有类型的声明. 如果要调用他们的技能 , gsl只能调用fire方法 , 而mds只能调用stone方法.我们程序员可以给这样的类型一个相当于强制装换的方案 如 : (<Godzilla>gsl).fire这样的写法很少见.记住就好.


四,索引类型:

function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
    return names.map(n => o[n]);
}

interface Person {
    name: string;
    age: number;
    add:( x : number , y : number ) => number;
}
let person: Person = {
    name: 'Jarid',
    age: 35,
    add:( x : number , y : number )=>{ return x + y ;},
};
let strings: Function[] = pluck(person, ['add']);

console.log( ` ${ strings[0](1,2) } ` );

结果:

keyof T 返回T的公共成员联合 , 如:

function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
    return names.map(n => o[n]);
}

interface Person {
    name: string;
    age: number;
    add:( x : number , y : number ) => number;
}
let person: Person = {
    name: 'Jarid',
    age: 35,
    add:( x : number , y : number )=>{ return x + y ;},
};
let strings: Function[] = pluck(person, ['add']);

//console.log( ` ${ strings[0](1,2) } ` );

//获取属性值
function getProperty<T, K extends keyof T>(o: T, name: K): T[K] {
    return o[name]; // o[name] is of type T[K]
}

let a : string = getProperty( person , 'name' );
console.log(a);

let b : Function = getProperty( person , 'add' );
console.log( `${b(2,3)}` );

结果: