TypeScript 高级类型

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

代码 :

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)}` );

结果:

时间: 2024-12-20 01:15:46

TypeScript 高级类型的相关文章

从C#到TypeScript - 高级类型

C# vs TypeScript - 高级类型 上一篇讲了基础类型,基本上用基础类型足够开发了,不过如果要更高效的开发,还是要看下高级类型,这篇和C#共同点并不多,只是延用这个主题. 联合类型 可以从字面上进行理解:其实就是多个类型联合在一起,用|符号隔开.如: string | number, 表示希望这个类型既可以是string,又可以是number.联合类型的字段只能调用这些类型共同拥有的方法,除非类型推论系统自动判断出真正的类型. //这里sn就是一个联合类型的字段,由于类型推论推断出s

TypeScript高级类型

交叉类型(Intersection Types) 交叉类型是将多个类型合并为一个类型. 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性. 例如,Person & Serializable & Loggable同时是Person和Serializable和Loggable. 就是说这个类型的对象同时拥有了这三种类型的成员. 我们大多是在混入(mixins)或其它不适合典型面向对象模型的地方看到交叉类型的使用. (在JavaScript里发生这种情况的场合很多

013 --TypeScript之高级类型

交叉类型可以简单理解为将多个类型合并成一个类型 function extend<T, U>(first: T, second: U): T & U { let result = {} as T & U for(let id in first) { result[id] = first[id] as any } for(let id in second){ if(!result.hasOwnProperty(id)){ result[id] = second[id] as any

Typescript #2 类型概览

原始类型 Javascript原始类型也同样适用于 TypeScript的类型系统.因此,string, number,boolean也可以被用作类型注解: let num: number; let str: string; let bool: boolean; num = 123; num = 123.45; num = '123'; //Type '"123"' is not assignable to type 'number' str = '123'; str = 123; /

TS(6)-- 类型推论、类型兼容性、高级类型

2019-11-09: 学习内容:类型推论.类型兼容性.高级类型 一.类型推论:类型是在哪里如何被推断的 在有些没有明确指出类型的地方,类型推论会帮助提供类型.如:let x = 3;  变量x的类型被推断为数字. 这种推断发生在初始化变量和成员,设置默认参数值和决定函数返回值时.大多数情况下,类型推论是直截了当地. 最佳通用类型:如: let x = [0, 1, null];   两种选择:number 和 null , 计算通用类型算法会考虑所有的候选类型,并给出一个兼容所有候选类型的类型

scala一些高级类型

package com.ming.test import scala.collection.mutable.ArrayBuffer import scala.io.Source import java.awt.image.BufferedImage import javax.imageio.ImageIO import java.io.File /** * 高级类型 */ //单例类型,链式调用 class Document{ def setTitle(title:String)={this}

【Go入门教程3】基本类型 和 高级类型

基本类型 Go 有很多预定义类型,这里简单地把它们分为 基本类型 和 高级类型.Go 的基本类型并不多,而且大部分都与整数相关,如下表所示: 名 称 宽度(字节) 零 值 说 明 bool 1 false 布尔类型,其值不为真即为假.真用常量 true 表示,假由常量 false 表示 byte 1 0 字节类型,它也可以看作是一个由 8 位二进制数表示的无符号整数类型 rune 4 0 rune 类型,它是有 Go 语言定义的特有的数据类型,专用于存储 Unicode 字符.它也可以看作一个由

TypeScript入门三:TypeScript函数类型

TypeScript函数类型 TypeScript函数的参数 TypeScript函数的this与箭头函数 TypeScript函数重载 一.TypeScript函数类型 在上一篇博客中已经对声明TypeScript类型变量已经做了初步的解析,这里先回顾以下: 1 //声明函数 2 function add1(x:number,y:number):number{ 3 return x+y; 4 } 5 6 let add2 = function(x:number,y:number):number

TypeScript的类型

⒈TypeScript的类型 JavaScript语言的数据类型包括以下7种: 1.boolean(布尔),true || false 2.null,表明null值得特殊关键字,JavaScript是大小写敏感的,不要误写成Null或者NULL 3.undefined,变量未定义时的属性 4.number,表示数字,例如1.1.2等等 5.string,表示字符串,例如:“Hello World!” 6.symbol,一种数据类型(在ES6种新添加的类型),表示该实例唯一且不可改变. 7.obj