vscode 原生支持ts编译
在vscode 里 上部,终端下的运行任务中,有选择 typescript ,可以选择构建或者监听。
构建:是指一次 打包
监听:是每一次保存之后都会自动打包
在package.json中 表示可以通过指令完成
“scripts”: {
“build”:”tsc”,
“watch”:”tsc —watch”
}
问题
当你新建了一个 变量时 ,提示无法重新声明块范围变量“name”。
说明你申明的是全局变量,就需要 export对象 ,改变他的作用域。
同理可得,一个代码中,如果有export,import之类的代码,那么这个文件就会变成一个模块
export {};let name:number = 123;
类型声明:
基本数据类型和原来一样;
数组有两种申明方式;
//元组的概念,元组类似于数组,它是一个长度和类型都固定的数组
//1.长度固定 2.类型可以不一样
//在同一个作用域内部,相同的变量名 只能申明一次let name:number = 123;let b:string = "skjas";let c:string = "c";let nums:number[] = [1,2,3];let nums1:Array<Number> = [1,2,3];//元组的概念,元组类似于数组,它是一个长度和类型都固定的数组let point:[number,number] = [1,2];let person:[string,number] = ['1',2];//枚举类型,key的值是一个关联关系,可以指定任何value值,如果不指定,默认会给下标enum Gender {BOY = 1,GIRL = 2}//const 是常数枚举 ,会被编译成常量 ,不可更改const enum Color {Red,Yellow}console.log(Color.Red,Color.Yellow)//任意类型 any//引入了第三方库,没有进行类型定义, 类型转换的时候 ,数据结构太灵活的时候 用any//当使用 any 时 ,就是默认数据类型了let root: any = document.getElementById('root');//ts为所有的dom类型提供了一整套的类型申明let root: HTMLElement | null = document.getElementById('root');//断言//对象的! 表示开发者自己定义的 一定会保证存在的值 (断言不为空)//对象的? 表示如果有就赋值root!.style.color = 'red';// null空 undefined未定义//他们都是其他类型的子类型 你可以把它们赋值给其它类型的变量let myname: string|null = null;let myname1: string = undefined;//void类型 空的 (没有的意思)//void可以返回 null 和undefinedfunction greeting(name: string): void {return null;//也可以不返回}//never 永远不//never 是其他类型的子类型,代表永远不会出现的值//在函数内部永远会抛出错误,导致函数无法正常结束function createError(message:string):never{console.log(1)throw new Error('error');console.log('end point')}function sum():never{while(true){console.log('123')}console.log('end point')}
never使用场景
1.启动一个后天任务,后台任务本身是监听,就是一个死循环,时间环函数,计划任务
2.写一些单元测试 的时候,就是让当前函数报出错误,看会不会影响别的函数
| , || 和 & ,&&的区别
| 是运算符中的 ,比如 let a = 3 | 5; a就等于 7 这个是二进制 加减
||就是 短路运算符,let a=3 || 5; a=3,
&也是运算中的,3&5 = 1
&& 短路运算符中的 let a=3 || 5; a=5,
ts类型推论
ts会根据你赋值的类型,推测出变量的类型,如果你申明的时候没有赋值,那么就会使 any
包装对象 java装箱和拆箱
//自动在基本类型的对象类型之间切换
1.基本类型上没有方法
2.在内部迅速完成一个装箱的操作,把基本类型迅速包装成对象类型,然后用对象来调用方法
let name4:string ='asd';name4.toLocaleLowerCase(); //在运行到这里的时候,会自动把原来的string,变成包装对象。//然后就会可以使用 包装对象的方法
联合类型
就是可以同时申明两个类型 :let a : number | string
断言
不可以断言成没有申明的类型变量
:let a : number | string(a as string).toLocaleLowerCase();//断言 它是一个string ,然后就可以调用string的方法了(a as number).toFixed()它是一个number就可以调用number的方法
字面量类型
字面量类型 有点像枚举 ,申明后的值,赋值只可以是申明的这两个了
let Data: ‘Boy’ |’GIRL’;
Data=’Boy’;
Data=’GIRL’;
字面量类型和联合类型的比较
1.字符串字面量类型用来约束取值只能是某几个字符串中的一个,联合类型表示取值可以是多种类型中的一个
2.字符串字面量限定了使用过该字面量的地方,仅能接受特定的值,联合类型对于值没有限定,仅仅限定值的类型需要保持一致
函数
函数的定义
1.可以指定参数的类型和返回值的类型
//函数定义function hello(name: string): void {console.log(name)return null;}//type用来定义一个类型 或者类型别名type GetUserNameType = (firstname: string, lastname: string) => string;//函数表达式let getUserName: GetUserNameType = (firstname: string, lastname: string): string => {return firstname + lastname;}//可选参数//? 代表的是可传可不传,没写问号的,就表示必须要传,调用的时候要么都传,要么都不传function print(name: string, age?: number, home?: string) {}//默认参数function ajax(url: string, method: string = 'GET') {console.log(method)}//剩余参数function sum(...number: Array<number>) {return number.reduce((accu, item) => accu + item, 0)}//函数重载//跟java一样接受参数类型不同表示重载//写了重载方法后,在调用的时候,传入别的类型就会报错//重载和函数之间不能有别的空格或者代码let obj:any={};function attr(val:string):void;function attr(val:number):void;function attr(val:any):void{}
类
//如何定义类class Person {name: string = 'aa';age: number;constructor() {this.age = 10;}}let p1 = new Person();console.log(p1.name);console.log(p1.age);//存取器 getter setternamespace a {class Person {myName: string;constructor(name: string) {this.myName = name;}get name() {return this.myName;}set name(newValue: string) {this.myName = newValue.toLocaleUpperCase();}}let p = new Person('ass');console.log(p.name);p.name = 'jiagou';console.log(p.name);}//参数类型//public关键字指的是 ,把public申明的变量变成公开的,实例属性//相当于直接申明了 name:string ;namespace c {class Person {constructor(public name: string) {}}let p = new Person('ass');}//readonly//只能查看不能修改namespace b {class Person {constructor(public readonly name: string) {}}let p = new Person('ass');}//继承 ts跟设计模式相关/*** 子类继承父类后,子类的实例上,就拥有了父类中的属性和方法* 访问修饰符 public公开的 protected 受保护的 private私有的* public 自己 自己的子类和其他类都可以访问* protected 受保护的 自己和自己的子类可以访问,其他类不能访问* private 私有的只能自己访问,自己的子类不可以访问,其他类更不可以了*//*** static 静态属性 就是说不需要实例的属性,可以直接通过类名进行调用* 静态方法 同理* static申明的变量在 实例上, 平时申明的变量在原型(prototype)上*/namespace d {class Person {public name: string;protected age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}getName() {return this.name;}setName(newString: string) {this.name = newString}}class Student extends Person {stuNo: number;constructor(name: string, age: number, stuNo: number) {super(name, age);this.stuNo = stuNo;}}let stu = new Student("qwe", 123, 1);}
类装饰器
1.装饰器是一种特殊类型的申明,他能附加在类的申明、方法、属性或者参数上,可以修改类的行为
2.常见的装饰器有类装饰器,属性装饰器,方式装饰器和参数装饰器
3.装饰器的写法分为普通装饰器和装饰器工厂
namespace a {// 接口interface Person {xx: string;yy: string;}//装饰器 接收参数 是类对象function enhancer(target: any) {target.prototype.name = "Person";}//装饰器放在class 类上@enhancerclass Person {constructor() {}}let p = new Person();}//把类整个替换namespace b {//装饰器 接收参数 是类对象function enhancer() {return function (target: any) {return class extends Person {constructor(name: string, age: number) {super(name, age);}//返回的加强类getAge(){console.log(this.age);}}}}//装饰器放在class 类上 ,//这里的装饰器就变成了一个函数,去增强原来的类//注意 输出的 类要和原来的父类接收的类型一致@enhancer()class Person {name: string = 'persion';age:number = 10;constructor(name:string,age:number) {this.name=name;this.age=age }}let p = new Person('persion',10);console.log(p.age)}
属性装饰器
属性装饰器表达式会在运行时当作函数调用,传入下列参数
属性装饰器用来装饰属性
1.第一个参数对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
2.第二个参数是属性的名称
//属性装饰器 装饰属性namespace c {//target如果装饰的是一个普通属性,target 指向类的原型 prototype//target装饰一个类属性static ,那么target指向类的定义//propertyName属性名function upperCase(target: any, propertyName: string) {let value = target[propertyName];const getter = () => value;const setter = (newVal: string) => {value = newVal.toUpperCase();}delete target[propertyName];Object.defineProperty(target, propertyName, {get: getter,set: setter,enumerable: true,configurable: true})}//属性装饰器工厂function propertyEnumerable(flag: boolean) {return function (target: any, propertyName: string) {}}//方法装饰器工厂,就是返回一个装饰器function mehtodEnumerable(flag: boolean) {/*** @target 指向实例或者原型* @methodName 方法的名称* @propertyDescriptor 属性描述器的值*/return function (target: any, methodName: string, propertyDescriptor: PropertyDescriptor) {propertyDescriptor.enumerable = flag;}}//方法装饰器工厂,就是返回一个装饰器function setAge(age: number) {return function (target: any, methodName: string,) {target.age = age;}}function toNumber (target: any, methodName: string, propertyDescriptor: PropertyDescriptor){//取出老方法的值let oldMethod = propertyDescriptor.value;//老方法的值再去 转变格式propertyDescriptor.value= function(...args:any[]){//转变格式args=args.map(item=>parseFloat(item));//转变完成,调用 原来的方法return oldMethod.apply(this,args);}}class Person {static age: number;@upperCasename: string = "aa";age: number = 10;@mehtodEnumerable(true)getName() {console.log(1)}@setAge(100)static getAge() {}@toNumbersum(...args: any[]) {return args.reduce((accu, item) => accu + item, 0);}}let p = new Person();p.name = '架构';p.sum([1, '2', '3']) ////属性装饰器 装饰属性namespace c {//target如果装饰的是一个普通属性,target 指向类的原型 prototype//target装饰一个类属性static ,那么target指向类的定义//propertyName属性名function upperCase(target: any, propertyName: string) {let value = target[propertyName];const getter = () => value;const setter = (newVal: string) => {value = newVal.toUpperCase();}delete target[propertyName];Object.defineProperty(target, propertyName, {get: getter,set: setter,enumerable: true,configurable: true})}//属性装饰器工厂function propertyEnumerable(flag: boolean) {return function (target: any, propertyName: string) {}}//方法装饰器工厂,就是返回一个装饰器function mehtodEnumerable(flag: boolean) {/*** @target 指向实例或者原型* @methodName 方法的名称* @propertyDescriptor 属性描述器的值*/return function (target: any, methodName: string, propertyDescriptor: PropertyDescriptor) {propertyDescriptor.enumerable = flag;}}//方法装饰器工厂,就是返回一个装饰器function setAge(age: number) {return function (target: any, methodName: string,) {target.age = age;}}function toNumber (target: any, methodName: string, propertyDescriptor: PropertyDescriptor){//取出老方法的值let oldMethod = propertyDescriptor.value;//老方法的值再去 转变格式propertyDescriptor.value= function(...args:any[]){//转变格式args=args.map(item=>parseFloat(item));//转变完成,调用 原来的方法return oldMethod.apply(this,args);}}class Person {static age: number;@upperCasename: string = "aa";age: number = 10;@mehtodEnumerable(true)getName() {console.log(1)}@setAge(100)static getAge() {}@toNumbersum(...args: any[]) {return args.reduce((accu, item) => accu + item, 0);}}let p = new Person();p.name = '架构';p.sum([1, '2', '3']) //这里原来调用输入 123 ,但是重新改了以后就输出6}}
参数装饰器
//参数装饰器namespace d {//参数装饰 方法参数interface Person {age: number}//第一个参数 实例,第二个参数方法名,第三个参数,参数的索引function addAge(target: any, methodName: string, paramsIndex: number) {target.age = 10;}class Person {login(username: string, @addAge password: string) {console.log(this.age, username, password)}}let p = new Person();p.login('asd', "123")}
装饰器执行顺序

也就是 属性=》方法参数=》方法=》类
注意 :1.属性和方法 谁写在前面 谁就会先执行 ,最后才会是 类
2.同类型的,先执行后写的,然后依次向外
npm 配置源
装包的时候发现问题
1.当使用cnpm 和yarn 的装包时候,明明配置了源 。却访问到了npm 的源 ,然后报出 404的错误,
2.配置源地址的代码
一.通过命令配置1. 命令npm config set registry https://registry.npm.taobao.org2. 验证命令npm config get registry如果返回https://registry.npm.taobao.org,说明镜像配置成功。二、cnpm安装1. 安装cnpmnpm install -g cnpm --registry=https://registry.npm.taobao.org2. 使用cnpmcnpm install xxx
