Libraries such as RxJS use generics heavily in their definition files to describe how types flow through different interfaces and function calls. We can provide our own type information when we create Observables to enable all of the auto-complete & type-safety features that you would expect from Typescript. This can be achieved with minimal annotations thanks to the power of generics.

import Rx = require('rx');

Rx.Observable.interval(100)
.subscribe( (x) => {
console.log(x);
});

The way Typescript can understand the 'x' inside console.log() is type of number is because its type defination.

rx.all.d.ts:

    export interface ObservableStatic {
/**
* Returns an observable sequence that produces a value after each period.
*
* @example
* 1 - res = Rx.Observable.interval(1000);
* 2 - res = Rx.Observable.interval(1000, Rx.Scheduler.timeout);
*
* @param {Number} period Period for producing the values in the resulting sequence (specified as an integer denoting milliseconds).
* @param {Scheduler} [scheduler] Scheduler to run the timer on. If not specified, Rx.Scheduler.timeout is used.
* @returns {Observable} An observable sequence that produces a value after each period.
*/
interval(period: number, scheduler?: IScheduler): Observable<number>;
}

As we can see, the return type is number.

So interval return a number, but how in subscribe function also know 'x' is number type.

To understand that, we can go subscribe defination:

    export interface Observable<T> {
/**
* Subscribes an o to the observable sequence.
* @param {Mixed} [oOrOnNext] The object that is to receive notifications or an action to invoke for each element in the observable sequence.
* @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence.
* @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence.
* @returns {Diposable} A disposable handling the subscriptions and unsubscriptions.
*/
subscribe(observer: IObserver<T>): IDisposable;
/**
* Subscribes an o to the observable sequence.
* @param {Mixed} [oOrOnNext] The object that is to receive notifications or an action to invoke for each element in the observable sequence.
* @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence.
* @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence.
* @returns {Diposable} A disposable handling the subscriptions and unsubscriptions.
*/
subscribe(onNext?: (value: T) => void, onError?: (exception: any) => void, onCompleted?: () => void): IDisposable; /**
* Subscribes to the next value in the sequence with an optional "this" argument.
* @param {Function} onNext The function to invoke on each element in the observable sequence.
* @param {Any} [thisArg] Object to use as this when executing callback.
* @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
*/
subscribeOnNext(onNext: (value: T) => void, thisArg?: any): IDisposable;
/**
* Subscribes to an exceptional condition in the sequence with an optional "this" argument.
* @param {Function} onError The function to invoke upon exceptional termination of the observable sequence.
* @param {Any} [thisArg] Object to use as this when executing callback.
* @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
*/
subscribeOnError(onError: (exception: any) => void, thisArg?: any): IDisposable;
/**
* Subscribes to the next value in the sequence with an optional "this" argument.
* @param {Function} onCompleted The function to invoke upon graceful termination of the observable sequence.
* @param {Any} [thisArg] Object to use as this when executing callback.
* @returns {Disposable} A disposable handling the subscriptions and unsubscriptions.
*/
subscribeOnCompleted(onCompleted: () => void, thisArg?: any): IDisposable; /**
* Subscribes an o to the observable sequence.
* @param {Mixed} [oOrOnNext] The object that is to receive notifications or an action to invoke for each element in the observable sequence.
* @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence.
* @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence.
* @returns {Diposable} A disposable handling the subscriptions and unsubscriptions.
*/
forEach(observer: IObserver<T>): IDisposable; /**
* Subscribes an o to the observable sequence.
* @param {Mixed} [oOrOnNext] The object that is to receive notifications or an action to invoke for each element in the observable sequence.
* @param {Function} [onError] Action to invoke upon exceptional termination of the observable sequence.
* @param {Function} [onCompleted] Action to invoke upon graceful termination of the observable sequence.
* @returns {Diposable} A disposable handling the subscriptions and unsubscriptions.
*/
forEach(onNext?: (value: T) => void, onError?: (exception: any) => void, onCompleted?: () => void): IDisposable;
}

As we can see 'onNext' method it use '<T>' it get from the 'Observable<T>' interface. How's how TypeScript understand console.log(x)'s x should be number type.

So how can we create a type safe Observable by ourselves?

Rx.Observable.create( (observer) => {
observer.onNext({
path: '/user/share',
event: 'add'
})
}).subscribe( (x) => {
console.log(x);
});

For this part of code, we want Typescipt help us autocomplete and report error if we pass something like 'x.path1' which not exists.

First we add an interface:

interface FileEvent{
path: string,
event: 'add' | 'change'
}

We can add the interface to the subscribe, it will give the type checking and autocomplete:

Rx.Observable.create( (observer) => {
observer.onNext({
path: '/user/share',
event: 'add'
})
}).subscribe( (x: FileEvent) => {
console.log(x);
});

The problem for this is if you have multi subscriber, you don't want to copy this everywhere.

What actually we should do is provide the interface at the topest level:

Rx.Observable.create<FileEvent>( (observer) => {
observer.onNext({
path: '/user/share',
event: 'add'
})
}).subscribe( (x) => {
console.log(x);
});

To recap, create is a generic function which means we can pass a type when we call it. Then, thanks to the type definitions that are provided by the RxJS library, this type can now flow into the observer as you can see here, it enables type safety on the onNext method, and even makes it all the way through to the subscribe method.

[TypeScript] Understanding Generics with RxJS的更多相关文章

  1. [TypeScript] Understanding Decorators

    Decorators are a feature of TypeScript that are becoming more and more common in many major librarie ...

  2. [RxJS] Creating Observable From Scratch

    Get a better understanding of the RxJS Observable by implementing one that's similar from the ground ...

  3. TypeScript 零基础入门

    前言 2015 年末看过一篇文章<ES2015 & babel 实战:开发 npm 模块>,那时刚接触 ES6 不久,发觉新的 ES6 语法大大简化了 JavaScript 程序的 ...

  4. RxJS - Subject(转)

    Observer Pattern 观察者模式定义 观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态 ...

  5. 10 Essential TypeScript Tips And Tricks For Angular Devs

    原文: https://www.sitepoint.com/10-essential-typescript-tips-tricks-angular/ ------------------------- ...

  6. 8分钟为你详解React、Angular、Vue三大前端技术

    [引言] 当前世界中,技术发展非常迅速并且变化迅速,开发者需要更多的开发工具来解决不同的问题.本文就对于当下主流的前端开发技术React.Vue.Angular这三个框架做个相对详尽的探究,目的是为了 ...

  7. springcloud starter(一)

    Spring Cloud - Getting Started Example, 转载自:https://www.logicbig.com/tutorials/spring-framework/spri ...

  8. angular2版本迭代之特性追踪

    一. 2.0.0 升级到 2.4 升级前: 1.确保没有使用extends关键字实现OnInit的继承,以及没有用任何的生命周期中,而是全部改用implements. 2.停止使用deep impor ...

  9. angularCli打包遇到的一些问题

    有时在运行项目或者打包项目的时候会遇到报错信息:found version 4, expected 3, 这个大概意思是说该插件需要的依赖当前不支持,需要提高依赖的版本. 比如:@angular/co ...

随机推荐

  1. 移动端日期控件 mobiscroll

    Mobiscroll是一个用于触摸设备(Android phones, iPhone, iPad, Galaxy Tab)的日期和时间选择器jQuery插件.可以让用户很方便的只需要滑动数字既可以选择 ...

  2. javascript 获取 class 样式 重新赋值class样式 为div等系列标签内更改内容

    name = document.getElementById(project_not_through_id).className;                     // 获取目标id的 cla ...

  3. VC皮肤库之duilib

    首先是个国产的开源 的,directui 界面库,开放,共享,惠众,共赢,遵循bsd协议,可以免费用于商业项目,目前支持Windows 32 .Window CE.Mobile等平台. Duilib ...

  4. Python核心编程2第四章课后练习

    4-1 Python 对象.与所有 Python 对象有关的三个属性是什么?请简单的描述一下.      身份:对象的唯一标识      类型 :对象的类型决定了该对象可以保存什么类型的值       ...

  5. 实用lsof常用命令行

    1, 使用 lsof 命令行列出所有打开的文件 # lsof 这可是一个很长的列表,包括打开的文件和网络 上述屏幕截图中包含很多列,例如 PID.user.FD 和 TYPE 等等. FD - Fil ...

  6. Spring MVC 统一异常处理

    Spring MVC 统一异常处理 看到 Exception 这个单词都心慌 如果有一天你发现好久没有看到Exception这个单词了,那你会不会想念她?我是不会的.她如女孩一样的令人心动又心慌,又或 ...

  7. c++和java(c#)之间的pk

    个人认为本文较偏激,且年代较久远,但可以一看. 转自c++和java(c#)之间的pk 1.谁好谁坏? 如同当初我没有想到会进入java阵营一样,这次闯入c++阵营也是意料之外的.多年前,受到微软的影 ...

  8. iOS-NSTimer-pause-暂停-引用循环

    7月26日更新: 今天更新的主要目的是因为暂停!!!! 注:不推荐使用,并不是这样有错,而是因为这样写代码的规范问题,代码要有可读性,遵循代码即文档,使用暂停在团队合作中可能会带来误会,非必要不建议使 ...

  9. MockupBuilder

    玩一下,想起了以前公司产品经理作的些事了...

  10. lc面试准备:Number of 1 Bits

    1 题目 Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also ...