(跟新中。。。)
1.通过TS检测的万金油
let a as unknown as any
//嵌套函数 即函数内命名函数及调用,TS检测不到
const fn: (a: string[], cb: () => void ) => nerver = function(){
const annoy = function(){};// annoy就会逃脱TS的类型检测,因为TS属于结构类型系统,并不知道这个函数什么时候执行,所以也就不知道函数内部的实现
}
2 有趣的可联合辨识
即把一些具有相同结构和不同结构成员的数据类型通过联合|组成的联合类型;
那个相同的结构属性称做 可辨识的特征或 标签
interface Square {
kind: "square";
size: number;
}
interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
interface Circle {
kind: "circle";
radius: number;
}
// kind就是可辨识的联合特征
type Shape = Square | Rectangle | Circle;
function test(area: Square | Rectangle | Circle) {
if (area.kind === 'circle') {//(property) kind: "square" | "rectangle" | "circle"
return '3';
}
}
3.索引类型(Index types)
用法: 声明一个泛型T,一个泛型K extends keyof T,表示的就是K属于T的keys值的联合类型;T[K]就表示对应的成员K的类型
4.映射类型
旨在从旧的数据类型中生成新的数据类型,例如将成员改为只读或者可选属性
type Readonly<T> = {
readonly [P in keyof T]: T[P];
}
type Partial<T> = {
[P in keyof T]?: T[P];
}
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
type Record<K extends string, T> = {
[P in K]: T;
}
Exclude<T, U> -- 从T中剔除可以赋值给U的类型。
Extract<T, U> -- 提取T中可以赋值给U的类型。
NonNullable<T> -- 从T中剔除null和undefined。
ReturnType<T> -- 获取函数返回值类型。
InstanceType<T> -- 获取构造函数类型的实例类型。
5.在使用模块(外部模块)与命名空间(内部模块)的时候需要注意避免以下情况
- 文件的顶层声明是
export namespace Foo { ... }
(删除Foo
并把所有内容向上层移动一层) - 文件只有一个
export class
或export function
(考虑使用export default
) - 多个文件的顶层具有同样的
export namespace Foo {
(不要以为这些会合并到一个Foo
中!)
6.ts.config.json配置值讲解之一二
compileOnSave:是否在保存之后进行编译检查
baseUrl:项目的根路径,index.html里的会被命令行中的覆盖。
ouDir:输入路径
allowJs:是否允许js文件
moduleResolution: node或者classic模块解析方法
jsx:是否允许jsx语法 react
path:一些特殊的依赖模块的路径放置地,即对符合左边规则的一些依赖模块,会按照右侧的路径去寻找
rootDirs:相对虚拟路径,即在这里的路径下的文件会被合并到同一个目录下,即拥有同一个相对父路径。
7.巧用namespace
在es5中,如果我们定义了一个函数,如果要对函数进行扩展,那我们只能直接赋值操作,例如函数的静态方法,下面是es5的写法,我们重定了函数的name属性
var fn = (function a (Main){
Main.name = 'fn';
}(function (){}))
在TS中我们可以巧用namespace的合并实现
function fn(){console.log(fn.name)}
namespace fn{
export const name = 'fn';// 我们必须导出这个,才能够访问的到他
}
编译后的代码,可以看出和上面的写法基本一致
function fn() { console.log(fn.name); }
(function (fn) {
fn.name = 'fn';
})(fn || (fn = {}));
注意:类与类与变量无法合并
8.TS与React的结合
启用jsx,后缀名修改为.tsx
9, 注意装饰器的执行阶段--发生在声明阶段之后,而不是类实例化的时候。
function f() {
console.log(1);
return function(...a) {
console.log(a, 2);
};
}
@f()
class Test {
ss = '';
@f()
test() {
console.log(4);
}
constructor() {
this.ss = 'er';
}
}
看编译过之后的代码,其中_decorate和_metadata是TS库内的函数,目的是添加装饰器到目标上的,源码很简单,大家谷歌看一下就可以了
/**
* @return {?}
*/
function f() {
console.log(1);
return (/**
* @param {...?} a
* @return {?}
*/
function (...a) {
console.log(a, 2);
});
}
let Test = class Test {
constructor() {
this.ss = '';
this.ss = 'er';
}
/**
* @return {?}
*/
test() {
console.log(4);
}
};
__decorate([
f(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], Test.prototype, "test", null);
Test = __decorate([
f(),
__metadata("design:paramtypes", [])
], Test);
可以看到,f装饰的执行阶段就在class声明之后,优先class内部的方法,属性再之后是class自身