在用typescript进行开发的时候用npm package.json进行配置的时候用如下进行快速构建:
1、配置环境参看webpack, (需要安装typescript 与 ts-loader, 项目初始化的时候 tsc --init进行初始化,并且生成tsconfig文件)
2、typescriptr的基础类型(通过例子说明)
//布尔类型 let bool1: boolean = true; let bool2: boolean; //数值类型 let num1: number = 123; let num2: number; //字符串类型 let str1: string = 'are you ok???'; let str2: string; //数组类型 let arr1: number [] = [1, 2, 3]; let arr2: Array<number|string> = [1, 'test', 3]; let arr3: (number|string|boolean)[] = []; let arr4: Array<string> | Array<number>; //元组类型(与数组的区别在于元组必需全部元素类型都一致,并且一个都不能少) let yArr1: [string, number, boolean]; yArr1 = ['test', 2, true]; //枚举类型, 一般枚举名称第一个字母为大字 enum Role { AAA, BBB, CCC } console.log(Role.AAA, Role.BBB, Role.CCC); //也可以对枚举类型进行指定 enum Role2{ A = 1, B = 3, C = 5 } console.log(Role2.A, Role2.B, Role2, Role2[1]); enum Role3 { FIRST = Role2.A, SECOND = Role2.B } console.log(Role3); //any 类型 let any1: any = [1, 'test']; let any2: any = 'test'; //void 类型 //没有返回值的函数 let func = (...rest: Array<string|number|boolean|Function>): void => { console.log(rest); }; func('aaa', 1, true); //null 和 undefined 类型 let u: undefined = undefined; let n: null = null; //never类型 抛出错误的时候可用或者是死循环的时候可以用never类型 let errorFun = (msg: string): never =>{ throw new Error(msg); }; //object 类型 let obj1: {key: string, val: number} = {'key': 'abc', 'val': 10}; let obj2: object = {}; //map类型 let m1: Map<string, number> = new Map<string, number>(); m1.set('aaa', 20); console.log(m1, m1.get('aaa')); //set 类型 let s1: Set<string | number> = new Set<string | number>(); s1.add('haha'); s1.add(123); console.log(s1);
小技巧,如果想用已经定义好的变量的值引入对象中,那么需要用'[]'来修饰
enum Type { FIRST, SECOND, THIRD } let test: string = 'haha'; //对象中使用已定义好的类型 let json: object = { [Type.FIRST]: 'aaa', [Type.SECOND]: 'bbb', [Type.THIRD]: 'ccc', [test] : 'ddd' }; console.log(json); //输出 {0: "aaa", 1: "bbb", 2: "ccc", haha: "ddd"} interface IFix { type: Type } //如果继承了以上的接口,那么说明里面的值必需是Enum里的值 let obj: IFix = { type: Type.FIRST, // type: Type.SECOND }; //枚举类型中引用枚举类型 enum Check { GET = Type.FIRST, SET = Type.SECOND } console.log(Check); //定义对象的类型 let obj1: {[key: number]: string|number} = {0: 'aaa', 1: 'bbb', 3: 4}; //定义好数组对象的混合类型 let arr1: Array<{[key: number]: string}> = [{ 1: 'a', }];
3、类型断言
/** * 类型断言(有两种写法) * 一种用(<string>target) * 一种用(target as string) */ let getLength = function(target: string | number): number { if((<string>target).length) { return (target as string).length; } else { return target.toString().length; } };
4、Symbol对象的使用
let s1 = Symbol('test'); let s2 = Symbol('test'); console.log(s1 === s2); //输出 false; 因为两者是唯一的 let obj: object = { [s1]: 'abc', [s2]: 'efg' }; console.log(obj); //输出 {Symbol(test): "abc", Symbol(test): "efg"} //这种属性在object里面只能通过obj[s1]或者obj[s2]来访问,或者通过Object.getOwnPropertySymbols(obj)来获取全部的,其它的方式是不能访问到的 console.log(Object.getOwnPropertySymbols(obj)); //输出 [Symbol(test), Symbol(test)] //Symbol.for(key)表示会在全局搜索是否有check的Symbol对象,如果有,则返回创建好的对象,如果没有,那么就自行创建一个 let s3 = Symbol.for('check'); let s4 = Symbol.for('check'); console.log(s3 === s4); //返回true //Symbol.keyFor(symbolObject); console.log(Symbol.keyFor(s3)); //输出 check
5、接口类型
//对象的接口化 interface IArgs { name: string, //常规属性 age?: number, //可选属性 readonly sex: boolean, //只读属性 } //实现传入的参数接口化 let getInfo = (msg: IArgs): string => { return `my name is ${msg.name}, ${msg.age? "我今年是" + msg.age+ "岁了,": ''} 我的性别是msg.sex`; }; console.log(getInfo({ name: 'aaaa', age: 22, sex: true })); interface IObj { [key: number]: string } let obj2: IObj = {0: 'aaa', 1: 'bbb'}; interface IObject { age?: number, name: string, [name: number]: boolean } let o: IObject = { 1: true, age: 12, name: 'get', }; //数组接口化 interface IArr { 0: number, readonly 1: string, 2: boolean } let arr: IArr = [1, 'abc', false]; //接口函数化 interface IFunc { (name: string, age: number): string } let introduce: IFunc = function(name: string, age: number): string { return 'this is test'; }; console.log(introduce('test', 12)); //注意区别非接口化的类型指定 let introduce1: (name: string, age: number) => string = (name: string, age: number): string => { return 'this is also test'; }; //接口可以实现继承 interface IFirst { name: string } interface ISecond extends IFirst { age?: number, sex: number; }
6、函数
//可选参数用?来表示 let func1: (a: number, b: number, c?: number) => number = (a: number, b: number, c?: number) : number => { return a+b; }; console.log(func1(1,2)); //使用参数的默认值用=来表示 let func2: (name: string, age: number, dis: string) => string = (name: string, age: number, dis: string = 'test'): string => { return `${dis},name${name}, age: ${age}`; }; console.log(func2('aaa', 30, 'instroduce')); //使用剩余参数 let func3 = (n1: number, n2: number, ...ns: number[]): number => { let sum = 0; ns.forEach(value => sum +=value); return n1 * n2 + sum; }; console.log(func3(1,2,3,4));
7、泛型
//泛型函数一 function func1<T>(sign: T): T { return sign; } console.log(func1('check')); //泛型函数二 let func2: <T>(name: string, age: T) => string = <T>(name: string, age: T): string => { if(typeof age === 'number') { return '' + age; } return `${name}, ${age}`; }; //确定类型的泛型函数的调用 console.log(func2<string>('test', 'unknow')); //泛型函数三 //返回的是由泛型构成的数组 let func3: <T>(key: T, times: number) => T[] = <T>(key: T, times: number): Array<T> => { return new Array(times).fill(key); }; //调用 console.log(func3<number>(8, 6)); //输出 (6) [8, 8, 8, 8, 8, 8] //指定泛型属性 interface IT { length: number } let func4: <T extends IT> (key: T) => number = <T extends IT>(key: T): number => { return key.length; }; console.log(func4('are you ok???')); console.log(func4([1,2,3])); console.log(func4({length: 6})); //属性值的泛型指定 let func5: <T, K extends keyof T> (obj: T, props: K) => any = <T, K extends keyof T>(obj: T, props: K) => { return obj[props]; }; console.log(func5({name: 'aaa'}, 'name')); //console.log(func5({name: 'aaa'}, '')); 会报错 //接口中用泛型表示的方法有两种 interface ITest <T>{ //这种表示方法则表示里面的全部适用泛型 (name: string, age: number, type: T): string, (arr: Array<T>): T[] } //这种方法则表示,只是里面声明行的是泛型 interface ICheck { <T>(name: T, age: number): string, (arr: Array<string>): string }
let func = <T,U>(obj1:T, obj2: U): T & U => { // let obj = {} as T & U; //类型断言 // obj = Object.assign(obj1, obj2); // return obj; return Object.assign(obj1, obj2); };
interface Obj<T> { [key: number]: T; } const key: keyof Obj<number>; // keys的类型为number //这里需要注意,在讲接口一节时,讲索引类型的时候我们讲过,如果索引类型为 number,那么实现该接口的对象的属性名必须是 number 类型;但是如果接口的索引类型是 string 类型,那么实现该接口的对象的属性名设置为数值类型的值也是可以的,因为数值最后还是会先转换为字符串。这里一样,如果接口的索引类型设置为 string 的话,keyof Obj<number>等同于类型number | string: interface Obj<T> { [key: string]: T; } let key: keyof Obj<number>; // keys的类型为number | string key = 123; // right //也可以使用访问操作符,获取索引签名的类型: interface Obj<T> { [key: string]: T; } const obj: Obj<number> = { age: 18 }; let value: Obj<number>["age"]; // value的类型是number,也就是name的属性值18的类型
8、typescript里的get和set存取器(也可称魔术方法)
let obj: {[key: string]: string} = { _name: 'aaa', set name (val: string) { console.log(val); this._name = val; }, get name () { console.log('现在在取数'); return this._name; } }; console.log(obj.name); obj.name = 'are you ok???'; console.log(obj.name); //get set 方法在类中的使用 class Info { private _name: string; public constructor(name: string) { this._name = name; } public get name(): string{ console.log('这个类里面的get方法'); return this._name; } public set name(newValue: string) { console.log('这个是类里面的set方法'); this._name = newValue; } public getName() { return this._name; } } let info = new Info('aaa'); console.log(info.name); info.name = 'this is test'; console.log(info.name); console.log(info.getName());
9、typescript 中的类与接口的实现
interface IClass { name: string; getName(): string; } class Info implements IClass { public name: string; public constructor(name: string) { this.name = name; } public getName(): string { return this.name; } public setType<T>(type: T, times: number): T[] { console.log(this.name); return new Array(times).fill(type); } }
10、模块的引入和输出
A、输出
//模块的输出 //变量的输出 export let text: string = 'this is test'; //对象的输出 export let obj: {name: string, age: number} = { name: 'aaa', age: 20 }; //函数的输出 export let func1 = (name: string, age: number): string => { return `${name}, ${age}`; }; //输出一个集合 let str = 'aaa'; let obj1: {[name: string]: string | number} = {'token': 123456}; let func2: (num: number) => void = (num: number): void => { console.log('ok'); }; export { str, obj1, func2 } //输出一个类 export class Test { public constructor() { } } //输出一个默认的内容可以用export default,但是一个类只能有一个export default //一般使用在一个文件只有一个类或者function的情况下 export default class Check { public constructor() {} }
如果引入npm包的时候的输出写法
let str: string = 'this is test';
export = str;
B、引入
//引入全部模块,并起别名 import * as All from './tools/model'; //引入分块的模块 import {func1 as t, func2, obj} from "./tools/model"; //引入default模块 import layer from './tools/model'; //引入npm包,主要用自动化模块的引用 import vue = require('vue');
11、typescript的装饰器
a、类的装饰器
let state = function(target: any): void { //只接收一个参数,这个参数就是所装饰的类 target.prototype.say = function() { console.log('are you ok???'); } }; @state export default class Detail { private sign: boolean = false; public getSign(): boolean { return this.sign; } } let d = new Detail();
b、类里属性的装饰器
let sign = function(target: any, key: string): void { //具有两个属性,一个是类,一个是变量的名称 Object.defineProperty(target, key, { get() { return 'are you ok???'; } }) }; export default class Detail { @sign private state: string; public getInfo(): void { console.log(this.state); } } let d = new Detail(); d.getInfo(); //输出are you ok???
类里属性传参形式的装饰器
let property = function(isChange: boolean = false): (target: any, key: string) => void { //第一层外面传入的参数,第二层的参数和上面的参数一样 return function(target, key) { Object.defineProperty(target, key, { get() { return isChange? 'are you ok???': 'this is ok'; } }) } }; export default class Detail { @property(true) private str: string; public getStr(): void { console.log(this.str); } } let d = new Detail(); d.getStr();
const propDec = <T>(classT: T, prop: string|symbol) => { let temp: any; Object.defineProperty(classT, prop, { get() { return temp }, set(val) { temp = val + 'yes' } }) } class Test { @propDec private state: string public check(): void { this.state = 'test' console.log(this.state) this.state = 'abc' console.log(this.state) } } new Test().check()
c、类里方法的装饰器
let sign = function(target: any, key: string, obj: any): void { //接收三个参数,第一个是类的本身,第二个是方法名,第三个defineProperty的第三个参数,可以对value进行处理 let fn = obj.value; obj.value = function(...rest) { console.log('this is add'); return fn.apply(target, rest); } }; export default class Detail { @sign public getInfo(name: string): void { console.log(name, 'okok'); } } let d = new Detail(); console.log(d.getInfo('yf')); //输出this is add, yf okok
d、类里参数的装饰器
let property = function(target: any, key: string, index: number){ console.log(index); //输出的是参数索引,如果修饰的是第一位参数则为0 }; export default class Detail { public getStr(@property name): void { console.log(name); } } let d = new Detail(); d.getStr('test');