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

代码 :

function extend
(first: T, second: U): T & U {    let result = 
{};    for (let id in first) {        (
result)[id] = (
first)[id];    }    for (let id in second) {        if (!result.hasOwnProperty(id)) {            (
result)[id] = (
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((
gsl).fire());//(
gsl).fireconsole.log((
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
(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
(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
(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)}` );

结果: