TypeScript(三)

89 阅读3分钟

1、泛型

Ⅰ. 泛型优化

// 常规写法:
function setNum(a:number,b:number):Array<number> {
    return [a,b]
}
function setStr(a:string,b:string):Array<string> {
    return [a,b]
}

// 利用泛型优化
// 函数名<T>
function setTypeData<T>(a: T, b:T):Array<T> {
    return [a,b]
}
const generic_num = setTypeData<number>(1,2)
const generic_boolean = setTypeData(true,false)

Ⅱ. type

type Generic_Type<T> = number | string | T
let gen_A: Generic_Type<boolean> = 123
let gen_B: Generic_Type<boolean> = 'AAA'
let gen_C: Generic_Type<boolean> = true

Ⅲ. interface, 泛型接口

interface Gen_data<T> {
    msg: T
}
let gen_data1: Gen_data<number> = {
    msg: 1008611
}

Ⅳ. 定义多个泛型

function setGenData<T,K>(a: T,b:K) :Array<T | K>{
    return [a,b]
}
let gen_data2 = setGenData(1,false)

Ⅴ. 示例接口封装

// 实用场景:接口调用。
const gen_axios = {
    get<T>(url:string):Promise<T> {
        return new Promise((resolve,reject) => {
            let xhr:XMLHttpRequest = new XMLHttpRequest();
            xhr.open('GET',url);
            xhr.onreadystatechange = () => {
                if(xhr.readyState == 4 && xhr.status == 200) {
                    resolve(JSON.parse(xhr.responseText))
                }
            }
            xhr.send(null)
        })
    }
}

interface Gen_ax {
    code: number,
    message: string,
    data: object
}


gen_axios.get<Gen_ax>('./data.json')
.then(res => {
    console.log(res,'gen_axios')
})

注:ts无法识别XMLHttpRequest,需编译成js文件再运行。

2、泛型约束 keyof

Ⅰ. extends + 约束类型

// 泛型支持相加 || 获取length
function gen_add<T extends number>(a: T, b: T) {
  return a + b;
}
gen_add(1, 1);

interface Len {
  length: number;
}
function gen_len<T extends Len>(a: T) {
  return a.length;
}
gen_len("112233");
gen_len([1, 2, 3]);
// gen_len(112233)

Ⅱ. 使用keyof约束对象

// 定义T类型并使用extend关键字继承object类型的子类型,
// 然后使用keyof操作符获取T类型的所有键(K extends keyof T)
let gen_obj = {
  attack: 300,
  mana: "none",
  defense: "loading",
};

// keyof: 将对象的key推断为联合类型
type obj_typeof = typeof gen_obj; // 对象类型
type obj_keyof = keyof typeof gen_obj; //

function get_gen_obj<T extends object, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}
get_gen_obj(gen_obj, "attack");
// get_gen_obj(gen_obj,'age') // 报错

Ⅲ.keyof 高级用法

interface gen_In {
  name: string;
  age: number;
  sex: string;
}
// keyof 实现 for in
type gen_option<T extends object> = {
  [Key in keyof T]?: T[Key];
};
type gen_Ex = gen_option<gen_In>;

Ⅳ. 泛型类

class Gen_Class<T> {
  attr: T[] = [];
  add(a: T): T[] {
    return [a];
  }
}

let gen_class1 = new Gen_Class<number>();
gen_class1.attr = [2,3,3,3];
gen_class1.add(133)

let gen_class2 = new Gen_Class<string>();
gen_class2.attr = ['2','2','3']
gen_class2.add('loading')

3、tsconfig.json

blog.csdn.net/qq119556631…

// 生成tsconfig.json文件
tsc --init

4、namespace 命名空间

ts 提供namespace为命名冲突的一种解决方案

Ⅰ. export || namespace

通过export暴露,namespace关键字定义。

export const a = '123'

namespace A {
    export const a = 1008611
    export const time: number = 10010;
}
console.log(a);
console.log(A.a);

Ⅱ. 嵌套命名空间

namespace B {
    export const time: number = 1835;
    export namespace C {
        export const time: number = 3333
    }
}

console.log(A.time)
console.log(B.time)
console.log(B.C.time)

Ⅲ. 抽离命名空间

import { B } from './index.ts'
console.log(B.time)

Ⅳ. 简化命名空间

import X = B.C.time;
console.log(X,'X')

Ⅴ. 合并命名空间

// 重复再合并,同interface
namespace AA {
    export const b: string = 'AA.b';
}
namespace AA {
    export const c:string = 'AA.c'
}

console.log(AA.b);
console.log(AA.c);

Ⅵ.  命名空间的案例

应用场景:跨端项目调用不同平台的能力,如:h5 android 小程序等。

namespace ios {
  export const pushNotification = (msg: string, type: number) => {};
}

namespace android {
    export const pushNotification = (msg: string ) => {}
    export const callPhone = (phone: number) => {}
}

namespace miniProgram {
    export const pushNotification = (msg: string) => {}
}

5、三斜线指令

包含单个XML标签的单行注释,注释的内容会做为编译器指令使用。

// Ⅰ. 引入额外的文件
///<reference path="9 class.ts"/>


// Ⅱ. 引入声明文件
// npm i @types/node
 // ///<reference type="node" />

示例:index.ts 引入其他ts文件

namespace A {
    // export const fn1 = () => 'fn1'
    export const fn1 = 'fn1'
}

///<reference path="index2.ts"/>
///<reference path="index3.ts"/>


console.log(A)
console.log(A.fn1);
console.log(A.fn2);
console.log(A.fn3);

// 引入声明文件
///<reference type="node"/>
namespace A {
    export const fn2 = () => 'fn2'
}
namespace A {
    export const fn3 = () => 'fn3'
}

6、模块解析

在ES6模块化规范前,存在4种模块化解析方式,分别为

// ES6模块化规范之前
// 1、 Commonjs => Nodejs
// 导出
exports.xxx = function() {}
module.exports = xxx

// 导入
require('xxx')
require('../xxx.js')

// 2、AMD => requireJS
// 定义
// define("module",["dep1","dep2"], function(d1,d2){})
// 加载
// require(["module","../app"],function(module,app){})

// 3、CMD => SeaJS
define(function(require,exports,module){
    var a = require('./a');
    a.doSomething();
})

// 4、UMD =>CommonJS和AMD的糅合
(function (window,factory){
    // 判断是否node环境
    if(typeof module === 'object' && typeof module.exports === 'object') {
        module.exports = factory();
    }
    // 判断是否AMD规范
    else if(typeof define === 'function' && define.amd) {
        define(factory)
    }

    // 使用浏览器环境
    else {
        window.eventUtil = factory()
    }
})(this, function() {
    // module
})

ES6模块化规范

Ⅰ. 默认导出

// 导出:constants.ts
export default {
    number: 1008611
}
// 导入
// import constants from './constants'

Ⅱ. 分别导出

export const a = 1;
export function add<T extends number>(a: T, b: T) {
    return a + b
}
// 导入
// import { a as a_rename,add } from './2'
// import * as util from './2'

Ⅲ. 动态引入

通过import方法动态引入,.then接收

if(true) {
    import('./test').then(res => {
        console.log(res)
    })
}