当前位置:网站首页>LayaBox - TypeScript - merge statement
LayaBox - TypeScript - merge statement
2022-08-02 10:11:00 【Gamla granite】
目录
1.介绍
TypeScript中有些独特的概念可以在类型层面上描述JavaScript对象的模型. 这其中尤其独特的一个例子是“声明合并”的概念. 理解了这个概念,将有助于操作现有的JavaScript代码. 同时,也会有助于理解更多高级抽象的概念.
对本文件来讲,“声明合并”是指编译器将针对同一个名字的两个独立声明合并为单一声明. 合并后的声明同时拥有原先两个声明的特性. 任何数量的声明都可被合并;不局限于两个声明.
2.基础概念
TypeScript中的声明会创建以下三种实体之一:命名空间、类型 或 值.
创建命名空间的声明会新建一个命名空间,它包含了用(.)符号来访问时使用的名字. 创建类型的声明是:用声明的模型创建一个类型并绑定到给定的名字上. 最后,创建值的声明会创建在JavaScript输出中看到的值.
| Declaration | Namespace | Type | Value |
| Namespace | X | X | |
| Class | X | X | |
| Enum | X | X | |
| Interface | X | ||
| Type Alias | X | ||
| Function | X | ||
| Variable | X |
理解每个声明创建了什么,有助于理解当声明合并时有哪些东西被合并了.
3.合并接口
最简单也最常见的声明合并类型是接口合并.
interface Box {
height: number;
width: number;
}
interface Box {
scale: number;
}
let box: Box = {height: 5, width: 6, scale: 10};接口的非函数的成员应该是唯一的.
如果它们不是唯一的,那么它们必须是相同的类型.
如果两个接口中同时声明了同名的非函数成员且它们的类型不同,则编译器会报错.
对于函数成员,每个同名函数声明都会被当成这个函数的一个重载. 同时需要注意,当接口 A与后来的接口 A合并时,后面的接口具有更高的优先级.
interface Cloner {
clone(animal: Animal): Animal;
}
interface Cloner {
clone(animal: Sheep): Sheep;
}
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
}这三个接口合并成一个声明:
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
clone(animal: Sheep): Sheep;
clone(animal: Animal): Animal;
}️注意:Each set of statement sequence mouth remains the same,但各组接口之间的顺序是后来的接口重载出现在靠前位置.
这个规则有一个例外是当出现特殊的函数签名时. 如果签名里有一个参数的类型是 单一的字符串字面量(比如,不是字符串字面量的联合类型),那么它将会被提升到重载列表的最顶端.
interface Document {
createElement(tagName: any): Element;
}
interface Document {
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
}
interface Document {
createElement(tagName: string): HTMLElement;
createElement(tagName: "canvas"): HTMLCanvasElement;
}合并后的 Document将会像下面这样:
interface Document {
createElement(tagName: "canvas"): HTMLCanvasElement;
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
createElement(tagName: string): HTMLElement;
createElement(tagName: any): Element;
}4.合并命名空间
同名的命名空间也会合并其成员. 命名空间会创建出命名空间和值,我们需要知道这两者都是怎么合并的.
对于命名空间的合并,模块导出的同名接口进行合并,构成单一命名空间内含合并后的接口.
对于命名空间里值的合并,如果当前已经存在给定名字的命名空间,那么后来的命名空间的导出成员会被加到已经存在的那个模块里.
Animals声明合并示例:
namespace Animals {
export class Zebra { }
}
namespace Animals {
export interface Legged { numberOfLegs: number; }
export class Dog { }
}
等同于:
namespace Animals {
export interface Legged { numberOfLegs: number; }
export class Zebra { }
export class Dog { }
}下例提供了更清晰的说明:
namespace Animal {
let haveMuscles = true;
export function animalsHaveMuscles() {
return haveMuscles;
}
}
namespace Animal {
export function doAnimalsHaveMuscles() {
// Error, because haveMuscles is not accessible here
return haveMuscles;
}
}因为 haveMuscles并没有导出,只有 animalsHaveMuscles函数共享了原始未合并的命名空间可以访问这个变量. doAnimalsHaveMuscles函数虽是合并命名空间的一部分,但是访问不了未导出的成员.
5.命名空间与类和函数和枚举类型合并
命名空间可以与其它类型的声明进行合并. 只要命名空间的定义符合将要合并类型的定义.合并结果包含两者的声明类型.
5.1 合并命名空间和类
--这让我们可以表示内部类.
class Album {
label: Album.AlbumLabel;
}
namespace Album {
export class AlbumLabel { }
}合并规则与上面
合并命名空间In the section about rules,我们必须导出AlbumLabel类,好让合并的类能访问. 合并结果是一个类并带有一个内部类. 你也可以使用命名空间为类增加一些静态属性.
除了内部类的模式,你在JavaScript里,创建一个函数稍后扩展它增加一些属性也是很常见的. TypeScript使用声明合并来达到这个目的并保证类型安全.
function buildLabel(name: string): string {
return buildLabel.prefix + name + buildLabel.suffix;
}
namespace buildLabel {
export let suffix = "";
export let prefix = "Hello, ";
}
console.log(buildLabel("Sam Smith"));相似的,命名空间可以用来扩展枚举型:
enum Color {
red = 1,
green = 2,
blue = 4
}
namespace Color {
export function mixColor(colorName: string) {
if (colorName == "yellow") {
return Color.red + Color.green;
}
else if (colorName == "white") {
return Color.red + Color.green + Color.blue;
}
else if (colorName == "magenta") {
return Color.red + Color.blue;
}
else if (colorName == "cyan") {
return Color.green + Color.blue;
}
}
}6.非法的合并
TypeScript并非允许所有的合并. 目前,类不能与其它类或变量合并.
7.模块扩展
虽然JavaScript不支持合并,但你可以为导入的对象打补丁以更新它们.
// observable.js
export class Observable<T> {
// ... implementation left as an exercise for the reader ...
}
// map.js
import { Observable } from "./observable";
Observable.prototype.map = function (f) {
// ... another exercise for the reader
}它也可以很好地工作在TypeScript中, 但编译器对 Observable.prototype.map一无所知. 你可以使用扩展模块来将它告诉编译器:
// observable.ts stays the same
// map.ts
import { Observable } from "./observable";
declare module "./observable" {
interface Observable<T> {
map<U>(f: (x: T) => U): Observable<U>;
}
}
Observable.prototype.map = function (f) {
// ... another exercise for the reader
}
// consumer.ts
import { Observable } from "./observable";
import "./map";
let o: Observable<number>;
o.map(x => x.toFixed());模块名的解析和用
import/export解析模块标识符的方式是一致的. 当这些声明在扩展中合并时,就好像在原始位置被声明了一样. 但是,你不能在扩展中声明新的顶级声明-仅可以扩展模块中已经存在的声明.
8.全局扩展
你也以在模块内部添加声明到全局作用域中.
// observable.ts
export class Observable<T> {
// ... still no implementation ...
}
declare global {
interface Array<T> {
toObservable(): Observable<T>;
}
}
Array.prototype.toObservable = function () {
// ...
}全局扩展与模块扩展的行为和限制是相同的.
边栏推荐
- c#反射和特性
- 食品安全 | 鱼肝油不是鱼油,家有宝宝的注意了
- The ggbarplot function of the R language ggpubr package visualizes the grouped histogram, sets the add parameter to mean_se to visualize the histogram of the mean values of different levels and adds
- R语言ggplot2可视化:使用ggpubr包的ggbarplot函数可视化水平柱状图(条形图)、使用orientation参数设置柱状图转置为条形图
- List-based queuing and calling system
- ConvNeXt论文及实现
- Shell script realizes multi-select DNS simultaneous batch resolution of domain name IP addresses (new update)
- Implementation of mysql connection pool
- Naive Bayesian Method of Li Hang's "Statistical Learning Methods" Notes
- 读博一年后对机器学习工程的思考
猜你喜欢

ConvNeXt论文及实现

Re22:读论文 HetSANN An Attention-based Graph Neural Network for Heterogeneous Structural Learning

日元疲软令游戏机在日本变身“理财产品”:黄牛大赚

21年毕业转行软件测试,从0收入到月薪过万,我真的很幸运...

MySql千万级分页优化,快速插入千万数据方法

WPF 截图控件之文字(七)「仿微信」

李航《统计学习方法》笔记之监督学习Supervised learning

周鸿祎称微软抄袭 360 安全模式后发文否认;英特尔CEO基辛格回应市值被AMD超越:股价下跌是咎由自取|极客头条...

日元疲软令游戏机在日本变身“理财产品”:黄牛大赚

Linux system uninstall, install, upgrade, migrate clickHouse database
随机推荐
MSYS2 QtCreator Clangd 代码分析找不到 mm_malloc.h的问题补救
DVWA Clearance Log 2 - Command Injection
STL中list实现
【OpenCV】-霍夫变换
鸿星尔克再捐一个亿
Verilog's random number system task----$random
你认同这个观点吗?大多数企业的数字化都只是为了缓解焦虑
重磅大咖来袭!阿里云生命科学与智能计算峰会精彩内容剧透
如何安装dosbox(pycharm详细安装教程)
【New Edition】DeepFakes: Creation, Detection and Influence
软件工程国考总结——选择题
Use compilation to realize special effects of love
从零开始Blazor Server(5)--权限验证
LayaBox---TypeScript---三斜线指令
用汇编实现爱心特效【七夕来袭】
身为程序猿——谷歌浏览器的这些骚操作你真的废吗!【熬夜整理&建议收藏】[通俗易懂]
食品安全 | 鱼肝油不是鱼油,家有宝宝的注意了
第十六章 协程
Using the TCP protocol, will there be no packet loss?
The ggbarplot function of the R language ggpubr package visualizes the grouped histogram, sets the add parameter to mean_se to visualize the histogram of the mean values of different levels and adds