TypeScript基础入门之高级类型的交叉类型和联合类型

转发

TypeScript基础入门之高级类型的交叉类型和联合类型

项目实践仓库

https://github.com/durban89/typescript_demo.git
tag: 1.4.2

为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能直接运行看到输出的结果。

npm install -D ts-node

后面自己在练习的时候可以这样使用

npx ts-node 脚本路径

高级类型

交叉类型(Intersection Types)

交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。 例如, Person & Serializable & Loggable同时是 Person 和 Serializable 和 Loggable。 就是说这个类型的对象同时拥有了这三种类型的成员。您将主要看到用于mixins的交集类型和其他不适合经典面向对象模具的概念。(在JavaScript中有很多这些!)这是一个简单的例子,展示了如何创建mixin:

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 AdvancedTypesClass {
    constructor(public name: string){}
}

interface LoggerInterface {
    log(): void;
}

class AdvancedTypesLoggerClass implements LoggerInterface {
    log(): void {
        console.log('console logging');
    }
}

var logger = new AdvancedTypesLoggerClass();

var extend1 = extend(new AdvancedTypesClass("string"), new AdvancedTypesLoggerClass());
var e = extend1.name;
console.log(e);
extend1.log();

编译运行,注意这里要编译运行,我使用ts-node已经不能运行成功了。可能是哪里配置的有问题,具体步骤如下。

tsc ./src/advanced_types_1.ts
$ node ./src/advanced_types_1.js
string
console logging

联合类型(Union Types)

联合类型与交叉类型很有关联,但是使用上却完全不同。 偶尔你会遇到这种情况,一个代码库希望传入 number或 string类型的参数。 例如下面的函数:

/**
 * 为给定的字符串左侧添加"padding"
 * 如果"padding"是一个字符串,则添加将字符串添加到给定字符串的左侧
 * 如果"padding"是一个数字,则添加padding个数量的空格到给定字符串的左侧
 */
function padLeft(value: string, padding: any) {
    if (typeof padding === 'string') {
        return padding + value;
    }

    if (typeof padding === 'number') {
        return Array(padding + 1).join(' ') + value;
    }

    throw new Error(`Excepted string or number, got ${padding}`);
}
console.log("|" + padLeft("string", 4) + "|");
console.log("|" + padLeft("string", "a") + "|");

编译并运行后得到如下结果

$ tsc ./src/advanced_types_1.ts && node ./src/advanced_types_1.js
|    string|
|astring|

padLeft有一个问题,就是padding这个参数是一个any类型,那就意味着我们可以在传递参数的时候,参数的类型可以是number或者是string,而TypeScript将会正常解析,
如果如下的方式调用,编译的时候是可以正常解析的,但是运行的时候回报错

padLeft("Hello world", true);

在传统的面向对象语言里,我们可能会将这两种类型抽象成有层级的类型。 这么做显然是非常清晰的,但同时也存在了过度设计。 padLeft原始版本的好处之一是允许我们传入原始类型。 这样做的话使用起来既简单又方便。 如果我们就是想使用已经存在的函数的话,这种新的方式就不适用了。除了any, 我们可以使用"联合类型"做为padding的参数,如下:

/**
 * 为给定的字符串左侧添加"padding"
 * 如果"padding"是一个字符串,则添加将字符串添加到给定字符串的左侧
 * 如果"padding"是一个数字,则添加padding个数量的空格到给定字符串的左侧
 */
function padLeft(value: string, padding: string | number) {
    if (typeof padding === 'string') {
        return padding + value;
    }

    if (typeof padding === 'number') {
        return Array(padding + 1).join(' ') + value;
    }

    throw new Error(`Excepted string or number, got ${padding}`);
}
console.log("|" + padLeft("string", 4) + "|");
console.log("|" + padLeft("string", "a") + "|");
console.log("|" + padLeft("string", true) + "|");

编译并运行后得到如下结果

$ tsc ./src/advanced_types_1.ts && node ./src/advanced_types_1.js
src/advanced_types_1.ts:65:37 - error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'.

65 console.log("|" + padLeft("string", true) + "|");

从实例演示可以看出,当传入一个boolean类型值的时候,在编辑的时候TypeScript就做出了判断,表示boolean类型的参数不被支持

联合类型表示一个值可以是几种类型之一。 我们用竖线(|)分隔每个类型,所以 number | string | boolean表示一个值可以是 number, string,或 boolean。

如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员,如下实例

interface Type1 {
    func1(): void;
    func2(): void;
}

interface Type2 {
    func3(): void;
    func2(): void;
}

class Type1Class implements Type1 {
    func1(): void {
        console.log('func1 run');
    }

    func2(): void {
        console.log('func2 run');
    }
}

class Type2Class implements Type2 {
    func3(): void {
        console.log('func1 run');
    }

    func2(): void {
        console.log('func2 run');
    }
}

function getSomeType(type: string): Type1Class | Type2Class {
    if (type === '1') {
        return new Type1Class();
    }

    if (type === '2') {
        return new Type2Class();
    }

    throw new Error(`Excepted Type1Class or Type2Class, got ${type}`);
}

let type = getSomeType('1');
type.func2();
type.func1(); // 报错

编译并运行后得到如下结果

$ tsc ./src/advanced_types_1.ts
src/advanced_types_1.ts:111:6 - error TS2551: Property 'func1' does not exist on type 'Type1Class | Type2Class'. Did you mean 'func2'?
  Property 'func1' does not exist on type 'Type2Class'.

111 type.func1();

这里的联合类型可能有点复杂,但是你很容易就习惯了。 如果一个值的类型是 A | B,我们能够 确定的是它包含了 A 和 B中共有的成员。 这个例子里, Type1Class具有一个func1成员。 我们不能确定一个 Type1Class | Type2Class类型的变量是否有func1方法。 如果变量在运行时是Type1Class类型,那么调用type.func1()就出错了。

本实例结束实践项目地址

https://github.com/durban89/typescript_demo.git
tag: 1.4.3
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,599评论 18 139
  • TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,它由 Micr...
    Gukson666阅读 8,653评论 3 29
  • 转载地址 TypeScript基础入门 - 基础类型 项目实践仓库 为了保证后面的学习演示需要安装下ts-node...
    鹏鲲云之上阅读 533评论 0 1
  • 20170904(07/30)
    同在我心阅读 234评论 3 7
  • 我一直在感谢这个时代,因为经济上的富有,让我有更多的时间去陪伴老二的成长,因此我就有条件去从事我这份当母亲的事业了...
    精致典雅阅读 496评论 0 0