一 , 交叉类型(操作符 & ):
代码 :
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)}` );
结果: