TypeScript --- 快速学习
1. typescript是什么
- Typescript是由微软开发的一款开源的编程语言
- Typescript是Javascript的超集,遵循最新的ES5/ES6规范。TypeScript扩展了Javascript语法
- TypeScript更像后端Java、C#这样的面向对象语言可以让JS开发大型企业应用
- 越来越多的项目是基于TS的,比如VSCode、Angular6、Vue3、React16
- TS提供的类型系统可以帮助我们在写代码的时候提供更丰富的语法提示
- 在创建前的编译阶段经过类型系统的检查,就可以避免很多线上的错误
2. TypeScript安装和编译
2.1 安装
cnpm i typescript -g
复制代码
tsc helloworld.ts
复制代码
2.2 Vscode+TypeScript
2.2.1 生成配置文件
tsc --init
复制代码
{"compilerOptions": {/* Basic Options */"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. 指定ECMAScript的目标版本*/"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 指定模块代码的生成方式*/// "lib": [], /* Specify library files to be included in the compilation. 指定编译的时候用来包含的编译文件*/// "allowJs": true, /* Allow javascript files to be compiled. 允许编译JS文件*/// "checkJs": true, /* Report errors in .js files. 在JS中包括错误*/// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. 指定JSX代码的生成方式 是保留还是react-native或者react*/// "declaration": true, /* Generates corresponding '.d.ts' file.生成相应的类型声明文件 */// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. 为每个类型声明文件生成相应的sourcemap*/// "sourceMap": true, /* Generates corresponding '.map' file. 生成对应的map文件 */// "outFile": "./", /* Concatenate and emit output to single file. 合并并且把编译后的内容输出 到一个文件里*/// "outDir": "./", /* Redirect output structure to the directory.按原始结构输出到目标目录 */// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. 指定输入文件的根目录,用--outDir来控制输出的目录结构*/// "composite": true, /* Enable project compilation 启用项目编译*/// "removeComments": true, /* Do not emit comments to output. 移除注释*/// "noEmit": true, /* Do not emit outputs. 不要输出*/// "importHelpers": true, /* Import emit helpers from 'tslib'. */// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. 当目标是ES5或ES3的时候提供对for-of、扩展运算符和解构赋值中对于迭代器的完整支持*/// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule').r把每一个文件转译成一个单独的模块 *//* Strict Type-Checking Options *///"strict": true, /* Enable all strict type-checking options. 启用完全的严格类型检查 */// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. 不能使用隐式的any类型*/// "strictNullChecks": true, /* Enable strict null checks. 启用严格的NULL检查*/// "strictFunctionTypes": true, /* Enable strict checking of function types. 启用严格的函数类型检查*/// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions.启用函数上严格的bind call 和apply方法 */// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. 启用类上初始化属性检查*/// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type.在默认的any中调用 this表达式报错 */// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. 在严格模式下解析并且向每个源文件中发射use strict*//* Additional Checks */// "noUnusedLocals": true, /* Report errors on unused locals. 有未使用到的本地变量时报错 */// "noUnusedParameters": true, /* Report errors on unused parameters. 有未使用到的参数时报错*/// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. 当不是所有的代码路径都有返回值的时候报错*/// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. 在switch表达式中没有替代的case会报错 *//* Module Resolution Options */// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). 指定模块的解析策略 node classic*/// "baseUrl": "./", /* Base directory to resolve non-absolute module names. 在解析非绝对路径模块名的时候的基准路径*/// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. 一些路径的集合*/// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. 根目录的列表,在运行时用来合并内容*/// "typeRoots": [], /* List of folders to include type definitions from. 用来包含类型声明的文件夹列表*/// "types": [], /* Type declaration files to be included in compilation.在编译的时候被包含的类型声明 */// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking.当没有默认导出的时候允许默认导入,这个在代码执行的时候没有作用,只是在类型检查的时候生效 *///"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'.*/// "preserveSymlinks": true, /* Do not resolve the real path of symlinks.不要symlinks解析的真正路径 *//* Source Map Options */// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. 指定ts文件位置*/// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. 指定 map文件存放的位置 */// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. 源文件和sourcemap 文件在同一文件中,而不是把map文件放在一个单独的文件里*/// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. 源文件和sourcemap 文件在同一文件中*//* Experimental Options */// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. 启动装饰器*/// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */}
}
复制代码
2.2.2 执行编译
tsc
复制代码
2.2.3 vscode运行
- Terminal->Run Task-> tsc:build 编译
- Terminal->Run Task-> tsc:watch 编译并监听
2.2.4 npm scripts
- npm run 实际上是调用本地的 Shell 来执行对应的 script value,所以理论上能兼容所有 bash 命令
- Shell 在类 Unix 系统上是 /bin/sh,在 Windows 上是 cmd.exe
2.2.5 npm scripts 的 PATH
- npm run 会预置 PATH,对应包下的 node_modules/.bin 目录
3. 数据类型
3.1 布尔类型(boolean)
let married: boolean=false;
复制代码
3.2 数字类型(number)
let age: number=10;
复制代码
3.3 字符串类型(string)
let firstname: string='zfpx';
复制代码
3.4 数组类型(array)
let arr2: number[]=[4,5,6];
let arr3: Array<number>=[7,8,9];
复制代码
3.5 元组类型(tuple)
- 在 TypeScript 的基础类型中,元组( Tuple )表示一个已知
数量
和类型
的数组
let zhufeng:[string,number] = ['zhufeng',5];
zhufeng[0].length;
zhufeng[1].toFixed(2);
复制代码
元组 | 数组 |
---|---|
每一项可以是不同的类型 | 每一项都是同一种类型 |
有预定义的长度 | 没有长度限制 |
用于表示一个固定的结构 | 用于表示一个列表 |
const animal:[string,number,boolean] = ['zhufeng',10,true];
复制代码
3.6 枚举类型(enum)
- 事先考虑某一个变量的所有的可能的值,尽量用自然语言中的单词表示它的每一个值
- 比如性别、月份、星期、颜色、单位、学历
3.6.1 普通枚举
enum Gender{GIRL,BOY
}
console.log(`李雷是${Gender.BOY}`);
console.log(`韩梅梅是${Gender.GIRL}`);enum Week{MONDAY=1,TUESDAY=2
}
console.log(`今天是星期${Week.MONDAY}`);
复制代码
3.6.2 常数枚举
- 常数枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员。
- 假如包含了计算成员,则会在编译阶段报错
const enum Colors {Red,Yellow,Blue
}let myColors = [Colors.Red, Colors.Yellow, Colors.Blue];
复制代码
const enum Color {Red, Yellow, Blue = "blue".length};
复制代码
3.7 任意类型(any)
any
就是可以赋值给任意类型- 第三方库没有提供类型文件时可以使用
any
- 类型转换遇到困难时
- 数据结构太复杂难以定义
let root:any=document.getElementById('root');
root.style.color='red';
复制代码
let root:(HTMLElement|null)=document.getElementById('root');
root!.style.color='red';//非空断言操作符
复制代码
3.8 null 和 undefined
- null 和 undefined 是其它类型的子类型,可以赋值给其它类型,如数字类型,此时,赋值后的类型会变成 null 或 undefined
strictNullChecks
参数用于新的严格空检查模式,在严格空检查模式下, null 和 undefined 值都不属于任何一个类型,它们只能赋值给自己这种类型或者 any
let x: number;
x = 1;
x = undefined;
x = null; let y: number | null | undefined;
y = 1;
y = undefined;
y = null;
复制代码
3.9 void 类型
- void 表示没有任何类型
- 当一个函数没有返回值时,TS 会认为它的返回值是 void 类型。
function greeting(name:string):void {console.log('hello',name);//当我们声明一个变量类型是 void 的时候,它的非严格模式(strictNullChecks:false)下仅可以被赋值为 null 和 undefined//严格模式(strictNullChecks:true)下只能返回undefined//return null;//return undefined;
}
复制代码
3.10 never类型
never是其它类型(null undefined)的子类型,代表不会出现的值
3.10.1
- 作为不会返回( return )的函数的返回值类型
// 返回never的函数 必须存在 无法达到( unreachable ) 的终点
function error(message: string): never {throw new Error(message);
}
let result1 = error('hello');
// 由类型推论得到返回值为 never
function fail() {return error("Something failed");
}
let result = fail();// 返回never的函数 必须存在 无法达到( unreachable ) 的终点
function infiniteLoop(): never {while (true) {}
}
复制代码
3.10.2 strictNullChecks
- 在 TS 中, null 和 undefined 是任何类型的有效值,所以无法正确地检测它们是否被错误地使用。于是 TS 引入了 --strictNullChecks 这一种检查模式
- 由于引入了 --strictNullChecks ,在这一模式下,null 和 undefined 能被检测到。所以 TS 需要一种新的底部类型( bottom type )。所以就引入了 never。
// Compiled with --strictNullChecks
function fn(x: number | string) {if (typeof x === 'number') {// x: number 类型} else if (typeof x === 'string') {// x: string 类型} else {// x: never 类型// --strictNullChecks 模式下,这里的代码将不会被执行,x 无法被观察}
}
复制代码
3.10.3 never 和 void 的区别
- void 可以被赋值为 null 和 undefined的类型。 never 则是一个不包含值的类型。
- 拥有 void 返回值类型的函数能正常运行。拥有 never 返回值类型的函数无法正常返回,无法终止,或会抛出异常。
3.11 类型推论
- 是指编程语言中能够自动推导出值的类型的能力,它是一些强静态类型语言中出现的特性
- 定义时未赋值就会推论成any类型
- 如果定义的时候就赋值就能利用到类型推论
let username2;
username2 = 10;
username2 = 'zhufeng';
username2 = null;
复制代码
3.12 包装对象(Wrapper Object)
- JavaScript 的类型分为两种:原始数据类型(Primitive data types)和对象类型(Object types)。
- 所有的原始数据类型都没有属性(property)
- 原始数据类型
- 布尔值
- 数值
- 字符串
- null
- undefined
- Symbol
let name = 'zhufeng';
console.log(name.toUpperCase());console.log((new String('zhufeng')).toUpperCase());
复制代码
- 当调用基本数据类型方法的时候,JavaScript 会在原始数据类型和对象类型之间做一个迅速的强制性切换
let isOK: boolean = true; // 编译通过
let isOK: boolean = Boolean(1) // 编译通过
let isOK: boolean = new Boolean(1); // 编译失败 期望的 isOK 是一个原始数据类型
复制代码
3.13 联合类型
- 联合类型(Union Types)表示取值可以为多种类型中的一种
- 未赋值时联合类型上只能访问两个类型共有的属性和方法
let name: string | number;
console.log(name.toString());
name = 3;
console.log(name.toFixed(2));
name = 'zhufeng';
console.log(name.length);export {};
复制代码
3.14 类型断言
- 类型断言可以将一个联合类型的变量,指定为一个更加具体的类型
- 不能将联合类型断言为不存在的类型
let name: string | number;
console.log((name as string).length);
console.log((name as number).toFixed(2));
console.log((name as boolean));
复制代码
3.15 字面量类型
- 可以把字符串、数字、布尔值字面量组成一个联合类型
type ZType = 1 | 'One'|true;
let t1:ZType = 1;
let t2:ZType = 'One';
let t3:ZType = true;
复制代码
3.16 字符串字面量 vs 联合类型
- 字符串字面量类型用来约束取值只能是某
几个字符串
中的一个, 联合类型(Union Types)表示取值可以为多种类型
中的一种 - 字符串字面量 限定了使用该字面量的地方仅接受特定的值,联合类型 对于值并没有限定,仅仅限定值的类型需要保持一致
4. 函数
4.1 函数的定义
- 可以指定参数的类型和返回值的类型
function hello(name:string):void {console.log('hello',name);
}
hello('zfpx');
复制代码
4.2 函数表达式
- 定义函数类型
type GetUsernameFunction = (x:string,y:string)=>string;
let getUsername:GetUsernameFunction = function(firstName,lastName){return firstName + lastName;
}
复制代码
4.3 没有返回值
let hello2 = function (name:string):void {console.log('hello2',name);return undefined;
}
hello2('zfpx');
复制代码
4.4 可选参数
在TS中函数的形参和实参必须一样,不一样就要配置可选参数,而且必须是最后一个参数
function print(name:string,age?:number):void {console.log(name,age);
}
print('zfpx');
复制代码
4.5 默认参数
function ajax(url:string,method:string='GET') {console.log(url,method);
}
ajax('/users');
复制代码
4.6 剩余参数
function sum(...numbers:number[]) {return numbers.reduce((val,item)=>val+=item,0);
}
console.log(sum(1,2,3));
复制代码
4.7 函数重载
- 在Java中的重载,指的是两个或者两个以上的同名函数,参数不一样
- 在TypeScript中,表现为给同一个函数提供多个函数类型定义
let obj: any={};
function attr(val: string): void;
function attr(val: number): void;
function attr(val:any):void {if (typeof val === 'string') {obj.name=val;} else {obj.age=val;}
}
attr('zfpx');
attr(9);
attr(true);
console.log(obj);
复制代码
5. 类
5.1 如何定义类
- "strictPropertyInitialization": true /启用类属性初始化的严格检查/
- name!:string
class Person{name:string;getName():void{console.log(this.name);}
}
let p1 = new Person();
p1.name = 'zhufeng';
p1.getName();
复制代码
5.2 存取器
- 在 TypeScript 中,我们可以通过存取器来改变一个类中属性的读取和赋值行为
- 构造函数
- 主要用于初始化类的成员变量属性
- 类的对象创建时自动调用执行
- 没有返回值
class User {myname:string;constructor(myname: string) {this.myname = myname;}get name() {return this.myname;}set name(value) {this.myname = value;}
}let user = new User('zhufeng');
user.name = 'jiagou';
console.log(user.name);
复制代码
"use strict";
var User = /** @class */ (function () {function User(myname) {this.myname = myname;}Object.defineProperty(User.prototype, "name", {get: function () {return this.myname;},set: function (value) {this.myname = value;},enumerable: true,configurable: true});return User;
}());
var user = new User('zhufeng');
user.name = 'jiagou';
console.log(user.name);
复制代码
5.3 参数属性
class User {constructor(public myname: string) {}get name() {return this.myname;}set name(value) {this.myname = value;}
}let user = new User('zhufeng');
console.log(user.name);
user.name = 'jiagou';
console.log(user.name);
复制代码
5.4 readonly
- readonly修饰的变量只能在
构造函数
中初始化 - 在 TypeScript 中,const 是
常量
标志符,其值不能被重新分配 - TypeScript 的类型系统同样也允许将 interface、type、 class 上的属性标识为 readonly
- readonly 实际上只是在
编译
阶段进行代码检查。而 const 则会在运行时
检查(在支持 const 语法的 JavaScript 运行时环境中)
class Animal {public readonly name: stringconstructor(name:string) {this.name = name;}changeName(name:string){this.name = name;}
}let a = new Animal('zhufeng');
a.changeName('jiagou');
复制代码
5.5 继承
- 子类继承父类后子类的实例就拥有了父类中的属性和方法,可以增强代码的可复用性
- 将子类公用的方法抽象出来放在父类中,自己的特殊逻辑放在子类中重写父类的逻辑
- super可以调用父类上的方法和属性
class Person {name: string;//定义实例的属性,默认省略public修饰符age: number;constructor(name:string,age:number) {//构造函数this.name=name;this.age=age;}getName():string {return this.name;}setName(name:string): void{this.name=name;}
}
class Student extends Person{no: number;constructor(name:string,age:number,no:number) {super(name,age);this.no=no;}getNo():number {return this.no;}
}
let s1=new Student('zfpx',10,1);
console.log(s1);复制代码
5.6 类里面的修饰符
class Father {public name: string; //类里面 子类 其它任何地方外边都可以访问protected age: number; //类里面 子类 都可以访问,其它任何地方不能访问private money: number; //类里面可以访问, 子类和其它任何地方都不可以访问constructor(name:string,age:number,money:number) {//构造函数this.name=name;this.age=age;this.money=money;}getName():string {return this.name;}setName(name:string): void{this.name=name;}
}
class Child extends Father{constructor(name:string,age:number,money:number) {super(name,age,money);}desc() {console.log(`${this.name} ${this.age} ${this.money}`);}
}let child = new Child('zfpx',10,1000);
console.log(child.name);
console.log(child.age);
console.log(child.money);
复制代码
5.7 静态属性 静态方法
class Father {static className='Father';static getClassName() {return Father.className;}public name: string;constructor(name:string) {//构造函数this.name=name;}}
console.log(Father.className);
console.log(Father.getClassName());
复制代码
5.8 抽象类
- 抽象描述一种抽象的概念,无法被实例化,只能被继承
- 无法创建抽象类的实例
- 抽象方法不能在抽象类中实现,只能在抽象类的具体子类中实现,而且必须实现
abstract class Animal {name!:string;abstract speak():void;
}
class Cat extends Animal{speak(){console.log('喵喵喵');}
}
let animal = new Animal();//Cannot create an instance of an abstract class
animal.speak();
let cat = new Cat();
cat.speak();
复制代码
访问控制修饰符 | private protected public |
---|---|
只读属性 | readonly |
静态属性 | static |
抽象类、抽象方法 | abstract |
5.9 抽象类 vs 接口
- 不同类之间公有的属性或方法,可以抽象成一个接口(Interfaces)
- 而抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
- 抽象类本质是一个无法被实例化的类,其中能够实现方法和初始化属性,而接口仅能够用于描述,既不提供方法的实现,也不为属性进行初始化
- 一个类可以继承一个类或抽象类,但可以实现(implements)多个接口
- 抽象类也可以实现接口
abstract class Animal{name:string;constructor(name:string){this.name = name;}abstract speak():void;}interface Flying{fly():void}
class Duck extends Animal implements Flying{speak(){console.log('汪汪汪');}fly(){console.log('我会飞');}
}
let duck = new Duck('zhufeng');
duck.speak();
duck.fly();
复制代码
5.10 抽象方法
- 抽象类和方法不包含具体实现,必须在子类中实现
- 抽象方法只能出现在抽象类中
- 子类可以对抽象类进行不同的实现
abstract class Animal{abstract speak():void;
}
class Dog extends Animal{speak(){console.log('小狗汪汪汪');}
}
class Cat extends Animal{speak(){console.log('小猫喵喵喵');}
}
let dog=new Dog();
let cat=new Cat();
dog.speak();
cat.speak();
复制代码
5.11 重写(override) vs 重载(overload)
- 重写是指子类重写继承自父类中的方法
- 重载是指为同一个函数提供多个类型定义
class Animal{speak(word:string):string{return '动作叫:'+word;}
}
class Cat extends Animal{speak(word:string):string{return '猫叫:'+word;}
}
let cat = new Cat();
console.log(cat.speak('hello'));
//--------------------------------------------
function double(val:number):number
function double(val:string):string
function double(val:any):any{if(typeof val == 'number'){return val *2;}return val + val;
}let r = double(1);
console.log(r);
复制代码
5.12 继承 vs 多态
- 继承(Inheritance)子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性
- 多态(Polymorphism)由继承而产生了相关的不同的类,对同一个方法可以有不同的响应
class Animal{speak(word:string):string{return 'Animal: '+word;}
}
class Cat extends Animal{speak(word:string):string{return 'Cat:'+word;}
}
class Dog extends Animal{speak(word:string):string{return 'Dog:'+word;}
}
let cat = new Cat();
console.log(cat.speak('hello'));
let dog = new Dog();
console.log(dog.speak('hello'));
复制代码
6. 接口
- 接口一方面可以在面向对象编程中表示为
行为的抽象
,另外可以用来描述对象的形状
- 接口就是把一些类中共有的属性和方法抽象出来,可以用来约束实现此接口的类
- 一个类可以继承另一个类并实现多个接口
- 接口像插件一样是用来增强类的,而抽象类是具体类的抽象概念
- 一个类可以实现多个接口,一个接口也可以被多个类实现,但一个类的可以有多个子类,但只能有一个父类
6.1 接口
- interface中可以用分号或者逗号分割每一项,也可以什么都不加
6.1.1 对象的形状
//接口可以用来描述`对象的形状`,少属性或者多属性都会报错
interface Speakable{speak():void;name?:string;//?表示可选属性
}let speakman:Speakable = {speak(){},//少属性会报错name,age//多属性也会报错
}
复制代码
6.1.2 行为的抽象
//接口可以在面向对象编程中表示为行为的抽象
interface Speakable{speak():void;
}
interface Eatable{eat():void
}
//一个类可以实现多个接口
class Person implements Speakable,Eatable{speak(){console.log('Person说话');}eat(){}
}
class TangDuck implements Speakable{speak(){console.log('TangDuck说话');}eat(){}
}
复制代码
6.1.3 任意属性
//无法预先知道有哪些新的属性的时候,可以使用 `[propName:string]:any`,propName名字是任意的
interface Person {readonly id: number;name: string;[propName: string]: any;
}let p1 = {id:1,name:'zhufeng',age:10
}
复制代码
6.2 接口的继承
- 一个接口可以继承自另外一个接口
interface Speakable {speak(): void
}
interface SpeakChinese extends Speakable {speakChinese(): void
}
class Person implements SpeakChinese {speak() {console.log('Person')}speakChinese() {console.log('speakChinese')}
}
复制代码
6.3 readonly
- 用 readonly 定义只读属性可以避免由于多人协作或者项目较为复杂等因素造成对象的值被重写
interface Person{readonly id:number;name:string
}
let tom:Person = {id :1,name:'zhufeng'
}
tom.id = 1;
复制代码
6.4 函数类型接口
- 对方法传入的参数和返回值进行约束
interface discount{(price:number):number
}
let cost:discount = function(price:number):number{return price * .8;
}
复制代码
6.5 可索引接口
- 对数组和对象进行约束
- userInterface 表示:只要 index 的类型是 number,那么值的类型必须是 string
- UserInterface2 表示:只要 index 的类型是 string,那么值的类型必须是 string
interface UserInterface {[index:number]:string
}
let arr:UserInterface = ['zfpx1','zfpx2'];
console.log(arr);interface UserInterface2 {[index:string]:string
}
let obj:UserInterface2 = {name:'zhufeng'};复制代码
6.6 类接口
- 对类的约束
interface Speakable {name: string;speak(words: string): void
}
class Dog implements Speakable {name!: string;speak(words:string) {console.log(words);}
}
let dog = new Dog();
dog.speak('汪汪汪');
复制代码
6.7 构造函数的类型
- 在 TypeScript 中,我们可以用 interface 来描述类
- 同时也可以使用interface里特殊的new()关键字来描述类的构造函数类型
class Animal{constructor(public name:string){}
}
interface WithNameClass{new(name:string):Animal
}
function createAnimal(clazz:WithNameClass,name:string){return new clazz(name);
}
let a = createAnimal(Animal,'zhufeng');
console.log(a.name);
复制代码
7. 泛型
- 泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
- 泛型
T
作用域只限于函数内部使用
7.1 泛型函数
- 首先,我们来实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值
function createArray(length: number, value: any): Array<any> {let result: any = [];for (let i = 0; i < length; i++) {result[i] = value;}return result;
}
let result = createArray(3,'x');
console.log(result);
复制代码
使用了泛型
function createArray<T>(length: number, value: T): Array<T> {let result: T[] = [];for (let i = 0; i < length; i++) {result[i] = value;}return result;}
let result = createArray2<string>(3,'x');
console.log(result);
复制代码
7.2 类数组
- 类数组(Array-like Object)不是数组类型,比如
arguments
function sum(...parameters: number[]) {let args: IArguments = arguments;for (let i = 0; i < args.length; i++) {console.log(args[i]);}
}
sum(1, 2, 3);let root = document.getElementById('root');
let children: HTMLCollection = (root as HTMLElement).children;
children.length;
let nodeList: NodeList = (root as HTMLElement).childNodes;
nodeList.length;
复制代码
7.3 泛型类
class MyArray<T>{private list:T[]=[];add(value:T) {this.list.push(value);}getMax():T {let result=this.list[0];for (let i=0;i<this.list.length;i++){if (this.list[i]>result) {result=this.list[i];}}return result;}
}
let arr=new MyArray();
arr.add(1); arr.add(2); arr.add(3);
let ret = arr.getMax();
console.log(ret);
复制代码
7.5 泛型接口
- 泛型接口可以用来约束函数
interface Calculate{<T>(a:T,b:T):T
}
let add:Calculate = function<T>(a:T,b:T){return a;
}
add<number>(1,2);复制代码
7.6 多个类型参数
- 泛型可以有多个
function swap<A,B>(tuple:[A,B]):[B,A]{return [tuple[1],tuple[0]];
}
let swapped = swap<string,number>(['a',1]);
console.log(swapped);
console.log(swapped[0].toFixed(2));
console.log(swapped[1].length);
复制代码
7.7 默认泛型类型
function createArray3<T=number>(length: number, value: T): Array<T> {let result: T[] = [];for (let i = 0; i < length; i++) {result[i] = value;}return result;
}
let result2 = createArray3(3,'x');
console.log(result2);
复制代码
7.8 泛型约束
- 在函数中使用泛型的时候,由于预先并不知道泛型的类型,所以不能随意访问相应类型的属性或方法。
function logger<T>(val: T) {console.log(val.length); //直接访问会报错
}
//可以让泛型继承一个接口
interface LengthWise {length: number
}
//可以让泛型继承一个接口
function logger2<T extends LengthWise>(val: T) {console.log(val.length)
}
logger2('zhufeng');
logger2(1);
复制代码
7.9 泛型接口
- 定义接口的时候也可以指定泛型
interface Cart<T>{list:T[]
}
let cart:Cart<{name:string,price:number}> = {list:[{name:'zhufeng',price:10}]
}
console.log(cart.list[0].name,cart.list[0].price);
复制代码
7.10 泛型类型别名
- 泛型类型别名可以表达更复杂的类型
type Cart<T> = {list:T[]} | T[];
let c1:Cart<string> = {list:['1']};
let c2:Cart<number> = [1];
复制代码
7.11 泛型接口 vs 泛型类型别名
- 接口创建了一个新的名字,它可以在其他任意地方被调用。而类型别名并不创建新的名字,例如报错信息就不会使用别名
- 类型别名不能被 extends和 implements,这时我们应该尽量使用接口代替类型别名
- 当我们需要使用联合类型或者元组类型的时候,类型别名会更合适
8.结构类型系统
8.1 接口的兼容性
- 如果传入的变量和声明的类型不匹配,TS就会进行兼容性检查
- 原理是
Duck-Check
,就是说只要目标类型中声明的属性变量在源类型中都存在就是兼容的
interface Animal {name: string;age: number;
}interface Person {name: string;age: number;gender: number
}
// 要判断目标类型`Person`是否能够兼容输入的源类型`Animal`
function getName(animal: Animal): string {return animal.name;
}let p = {name: 'zhufeng',age: 10,gender: 0
}getName(p);
//只有在传参的时候两个变量之间才会进行兼容性的比较,赋值的时候并不会比较,会直接报错
let a: Animal = {name: 'zhufeng',age: 10,gender: 0
}
复制代码
8.2 基本类型的兼容性
//基本数据类型也有兼容性判断
let num : string|number;
let str:string='zhufeng';
num = str;//只要有toString()方法就可以赋给字符串变量
let num2 : {toString():string
}let str2:string='jiagour';
num2 = str2;
复制代码
8.3 类的兼容性
- 在TS中是结构类型系统,只会对比结构而不在意类型
class Animal{name:string
}
class Bird extends Animal{swing:number
}let a:Animal;
a = new Bird();let b:Bird;
//并不是父类兼容子类,子类不兼容父类
b = new Animal();
复制代码
class Animal{name:string
}
//如果父类和子类结构一样,也可以的
class Bird extends Animal{}let a:Animal;
a = new Bird();let b:Bird;
b = new Animal();复制代码
//甚至没有关系的两个类的实例也是可以的
class Animal{name:string
}
class Bird{name:string
}
let a:Animal ;
a = new Bird();
let b:Bird;
b = new Animal();
复制代码
8.4 函数的兼容性
- 比较函数的时候是要先比较函数的参数,再比较函数的返回值
8.4.1 比较参数
type sumFunc = (a:number,b:number)=>number;
let sum:sumFunc;
function f1(a:number,b:number):number{return a+b;
}
sum = f1;//可以省略一个参数
function f2(a:number):number{return a;
}
sum = f2;//可以省略二个参数
function f3():number{return 0;
}
sum = f3;//多一个参数可不行
function f4(a:number,b:number,c:number){return a+b+c;
}
sum = f4;
复制代码
8.4.2 比较返回值
type GetPerson = ()=>{name:string,age:number};
let getPerson:GetPerson;
//返回值一样可以
function g1(){return {name:'zhufeng',age:10};
}
getPerson = g1;
//返回值多一个属性也可以
function g2(){return {name:'zhufeng',age:10,gender:'male'};
}
getPerson = g2;
//返回值少一个属性可不行
function g3(){return {name:'zhufeng'};
}
getPerson = g3;
//因为有可能要调用返回值上的方法
getPerson().age.toFixed();
复制代码
8.5 函数参数的协变
- 目标如果能够兼容源就是可以的
type LogFunc = (a:number|string)=>void;
let log:LogFunc;function log1(a:number|string|boolean){console.log(a);
}
//目标如果能够兼容源就是可以的
log = log1;
复制代码
8.6 泛型的兼容性
- 泛型在判断兼容性的时候会先判断具体的类型,然后再进行兼容性判断
//接口内容为空没用到泛型的时候是可以的
//1.接口内容为空没用到泛型的时候是可以的
interface Empty<T>{}
let x!:Empty<string>;
let y!:Empty<number>;
x = y;//2.接口内容不为空的时候不可以
interface NotEmpty<T>{data:T
}
let x1!:NotEmpty<string>;
let y1!:NotEmpty<number>;
x1 = y1;//实现原理如下,称判断具体的类型再判断兼容性
interface NotEmptyString{data:string
}interface NotEmptyNumber{data:number
}
let xx2!:NotEmptyString;
let yy2!:NotEmptyNumber;
xx2 = yy2;
复制代码
8.7 枚举的兼容性
- 枚举类型与数字类型兼容,并且数字类型与枚举类型兼容
- 不同枚举类型之间是不兼容的
//数字可以赋给枚举
enum Colors {Red,Yellow}
let c:Colors;
c = Colors.Red;
c = 1;
c = '1';//枚举值可以赋给数字
let n:number;
n = 1;
n = Colors.Red;
复制代码
9.类型保护
- 类型保护就是一些表达式,他们在编译的时候就能通过类型信息确保某个作用域内变量的类型
- 类型保护就是能够通过关键字判断出分支中的类型
9.1 typeof 类型保护
function double(input: string | number | boolean) {if (typeof input === 'string') {return input + input;} else {if (typeof input === 'number') {return input * 2;} else {return !input;}}
}
复制代码
9.2 instanceof类型保护
class Animal {name!: string;
}
class Bird extends Animal {swing!: number
}
function getName(animal: Animal) {if (animal instanceof Bird) {console.log(animal.swing);} else {console.log(animal.name);}
}
复制代码
9.3 null保护
- 如果开启了
strictNullChecks
选项,那么对于可能为null的变量不能调用它上面的方法和属性
function getFirstLetter(s: string | null) {//第一种方式是加上null判断if (s == null) {return '';}//第二种处理是增加一个或的处理s = s || '';return s.charAt(0);
}
//它并不能处理一些复杂的判断,需要加非空断言操作符
function getFirstLetter2(s: string | null) {function log() {console.log(s!.trim());}s = s || '';log();return s.charAt(0);
}
复制代码
9.4 链判断运算符
- 链判断运算符是一种先检查属性是否存在,再尝试访问该属性的运算符,其符号为 ?.
- 如果运算符左侧的操作数 ?. 计算为 undefined 或 null,则表达式求值为 undefined 。否则,正常触发目标属性访问,方法或函数调用。
a?.b; //如果a是null/undefined,那么返回undefined,否则返回a.b的值.
a == null ? undefined : a.b;a?.[x]; //如果a是null/undefined,那么返回undefined,否则返回a[x]的值
a == null ? undefined : a[x];a?.b(); // 如果a是null/undefined,那么返回undefined
a == null ? undefined : a.b(); //如果a.b不函数的话抛类型错误异常,否则计算a.b()的结果a?.(); //如果a是null/undefined,那么返回undefined
a == null ? undefined : a(); //如果A不是函数会抛出类型错误
//否则 调用a这个函数
复制代码
链判断运算符 还处于 stage1 阶段,TS 也暂时不支持
9.5 可辨识的联合类型
- 就是利用联合类型中的共有字段进行类型保护的一种技巧
- 相同字段的不同取值就是可辨识
interface WarningButton{class:'warning',text1:'修改'
}
interface DangerButton{class:'danger',text2:'删除'
}
type Button = WarningButton|DangerButton;
function getButton(button:Button){if(button.class=='warning'){console.log(button.text1);}if(button.class=='danger'){console.log(button.text2);}
}
复制代码
9.6 in操作符
- in 运算符可以被用于参数类型的判断
interface Bird {swing: number;
}interface Dog {leg: number;
}function getNumber(x: Bird | Dog) {if ("swing" in x) {return x.swing;}return x.leg;
}
复制代码
9.7 自定义的类型保护
- TypeScript 里的类型保护本质上就是一些表达式,它们会在运行时检查类型信息,以确保在某个作用域里的类型是符合预期的
- 要自定义一个类型保护,只需要简单地为这个类型保护定义一个函数即可,这个函数的返回值是一个类型谓词
- 类型谓词的语法为
parameterName is Type
这种形式,其中parameterName
必须是当前函数签名里的一个参数名`
interface Bird {swing: number;
}interface Dog {leg: number;
}//没有相同字段可以定义一个类型保护函数
function isBird(x:Bird|Dog): x is Bird{return (<Bird>x).swing == 2;return (x as Bird).swing == 2;
}
function getAnimal(x: Bird | Dog) {if (isBird(x)) {return x.swing;}return x.leg;
}
复制代码
10. 类型变换
10.1 交叉类型
- 交叉类型(Intersection Types)表示将多个类型合并为一个类型
interface Bird {name: string,fly(): void } interface Person {name: string,talk(): void } type BirdPerson = Bird & Person; let p: BirdPerson = { name: 'zhufeng', fly() { }, talk() { } }; p.fly; p.name p.talk; 复制代码
10.2 typeof
- 可以获取一个变量的类型
//先定义类型,再定义变量
type People = {name:string,age:number,gender:string
}
let p1:People = {name:'zhufeng',age:10,gender:'male'
}
复制代码
//先定义变量,再定义类型
let p1 = {name:'zhufeng',age:10,gender:'male'
}
type People = typeof p1;
function getName(p:People):string{return p.name;
}
getName(p1);
复制代码
10.3 索引访问操作符
- 可以通过[]获取一个类型的子类型
interface Person{name:string;age:number;job:{name:string};interests:{name:string,level:number}[]
}
let FrontEndJob:Person['job'] = {name:'前端工程师'
}
let interestLevel:Person['interests'][0]['level'] = 2;
复制代码
10.4 keyof
- 索引类型查询操作符
interface Person{name:string;age:number;gender:'male'|'female';
}
//type PersonKey = 'name'|'age'|'gender';
type PersonKey = keyof Person;function getValueByKey(p:Person,key:PersonKey){return p[key];
}
let val = getValueByKey({name:'zhufeng',age:10,gender:'male'},'name');
console.log(val);
复制代码
10.5 映射类型
- 在定义的时候用in操作符去批量定义类型中的属性
interface Person{name:string;age:number;gender:'male'|'female';
}
//批量把一个接口中的属性都变成可选的
type PartPerson = {[Key in keyof Person]?:Person[Key]
}let p1:PartPerson={};
//也可以使用泛型
type Part<T> = {[key in keyof T]?:T[key]
}
let p2:Part<Person>={};
复制代码
10.6 内置工具类型
- TS 中内置了一些工具类型来帮助我们更好地使用类型系统
10.6.1 Partial
- Partial 可以将传入的属性由非可选变为可选,具体使用如下:
type Partial<T> = { [P in keyof T]?: T[P] };interface A {a1: string;a2: number;a3: boolean;
}type aPartial = Partial<A>;const a: aPartial = {}; // 不会报错
复制代码
10.6.2 Required
- Required 可以将传入的属性中的可选项变为必选项,这里用了 -? 修饰符来实现。
//type Required<T> = { [P in keyof T]-?: T[P] };interface Person{name:string;age:number;gender?:'male'|'female';
}
/*** type Require<T> = { [P in keyof T]-?: T[P] };*/
let p:Required<Person> = {name:'zhufeng',age:10,//gender:'male'
}
复制代码
10.6.3 Readonly
- Readonly 通过为传入的属性每一项都加上 readonly 修饰符来实现。
interface Person{name:string;age:number;gender?:'male'|'female';
}
//type Readonly<T> = { readonly [P in keyof T]: T[P] };
let p:Readonly<Person> = {name:'zhufeng',age:10,gender:'male'
}
p.age = 11;
复制代码
10.6.4 Pick
- Pick 能够帮助我们从传入的属性中摘取某一项返回
interface Animal {name: string;age: number;
}
/*** From T pick a set of properties K* type Pick<T, K extends keyof T> = { [P in K]: T[P] };*/
// 摘取 Animal 中的 name 属性
type AnimalSub = Pick<Animal, "name">; //{ name: string; }
let a:AnimalSub = {name:'zhufeng',age:10
}
复制代码
10.6.5 映射类型修饰符的控制
- TypeScript中增加了对映射类型修饰符的控制
- 具体而言,一个
readonly
或?
修饰符在一个映射类型里可以用前缀+
或-
来表示这个修饰符应该被添加或移除 - TS 中部分内置工具类型就利用了这个特性(Partial、Required、Readonly...),这里我们可以参考 Partial、Required 的实现
10.7 条件类型
- 在定义泛型的时候能够添加进逻辑分支,以后泛型更加灵活
10.7.1 定义条件类型
interface Fish {name: string
}
interface Water {name: string
}
interface Bird {name: string
}
interface Sky {name: string
}
//三元运算符
type Condition<T> = T extends Fish ? Water : Sky;
let condition: Condition<Fish> = { name: '水' };
复制代码
10.7.2 条件类型的分发
interface Fish {fish: string
}
interface Water {water: string
}
interface Bird {bird: string
}
interface Sky {sky: string
}type Condition<T> = T extends Fish ? Water : Sky;
//(Fish extends Fish ? Water : Sky) | (Bird extends Fish ? Water : Sky)
// Water|Sky
let condition1: Condition<Fish | Bird> = { water: '水' };
let condition2: Condition<Fish | Bird> = { sky: '天空' };
复制代码
10.7.3 内置条件类型
- TS 在内置了一些常用的条件类型,可以在 lib.es5.d.ts 中查看:
10.7.3.1 Exclude
- 从 T 可分配给的类型中排除 U
type E = Exclude<string|number,string>; let e:E = 10; 复制代码
10.7.3.2 Extract
- 从 T 可分配的类型中提取 U
type E = Extract<string|number,string>; let e:E = '1'; 复制代码
10.7.3.3 NonNullable
- 从 T 中排除 null 和 undefined
type E = NonNullable<string|number|null|undefined>;
let e:E = null;
复制代码
10.7.3.4 ReturnType
- 获取函数类型的返回类型
`
js function getUserInfo() { return { name: "zhufeng", age: 10 }; }
// 通过 ReturnType 将 getUserInfo 的返回值类型赋给了 UserInfo type UserInfo = ReturnType;
const userA: UserInfo = { name: "zhufeng", age: 10 };
##### 10.7.3.5 InstanceType<T>
- 获取构造函数类型的实例类型
```js
class Person{name:string;constructor(name){this.name = name;}getName(){console.log(this.name)}
}type P = InstanceType<typeof Person>;
let p:P = {name:'zhufeng',getName(){}};
复制代码
11.类型声明
- 声明文件可以让我们不需要将JS重构为TS,只需要加上声明文件就可以使用系统
- 类型声明在编译的时候都会被删除,不会影响真正的代码
11.1 普通类型声明
declare const $:(selector:string)=>{ //变量click():void;width(length:number):void;
};
declare let name:string; //变量
declare let age:number; //变量
declare function getName():string; //方法
declare class Animal{name:string} //类interface Person{ //声明接口name:string
}type Student = { //声明类型name:string
}|'string';
复制代码
11.2 外部枚举
- 外部枚举是使用
declare enum
定义的枚举类型 - 外部枚举用来描述已经存在的枚举类型的形状
declare enum Seasons {Spring,Summer,Autumn,Winter
}let seasons = [Seasons.Spring,Seasons.Summer,Seasons.Autumn,Seasons.Winter
];
复制代码
declare 定义的类型只会用于编译时的检查,编译结果中会被删除。上例的编译结果如下
var seasons = [Seasons.Spring,Seasons.Summer,Seasons.Autumn,Seasons.Winter
];
复制代码
也可以同时使用declare
和 const
declare const enum Seasons {Spring,Summer,Autumn,Winter
}let seasons = [Seasons.Spring,Seasons.Summer,Seasons.Autumn,Seasons.Winter
];
复制代码
编译结果
var seasons = [0 /* Spring */,1 /* Summer */,2 /* Autumn */,3 /* Winter */
];
复制代码
11.3 namespace
- 如果一个全局变量包括了很多子属性,可能使用namespace
- 在声明文件中的
namespace
表示一个全局变量包含很多子属性 - 在命名空间内部不需要使用 declare 声明属性或方法
declare namespace ${function ajax(url:string,settings:any):void;let name:string;namespace fn {function extend(object:any):void;}
}
$.ajax('/api/users',{});
$.fn.extend({log:function(message:any){console.log(message);}
});
export {};复制代码
11.4 类型声明文件
- 我们可以把类型声明放在一个单独的类型声明文件中
- 可以在类型声明文件中使用类型声明
- 文件命名规范为
*.d.ts
- 观看类型声明文件有助于了解库的使用方式
11.4.1 jquery.d.ts
typings\jquery.d.ts
declare const $:(selector:string)=>{click():void;width(length:number):void;
}
复制代码
11.4.2 tsconfig.json
tsconfig.json
{"compilerOptions": {"module": "commonjs","target": "ES2015", "outDir":"lib"},"include": ["src/**/*","typings/**/*"]
}
复制代码
11.4.3 test.js
$('#button').click();
$('#button').width(100);
export {};
复制代码
11.5 第三方声明文件
- 可以安装使用第三方的声明文件
- @types是一个约定的前缀,所有的第三方声明的类型库都会带有这样的前缀
- JavaScript 中有很多内置对象,它们可以在 TypeScript 中被当做声明好了的类型
- 内置对象是指根据标准在全局作用域(Global)上存在的对象。这里的标准是指 ECMAScript 和其他环境(比如 DOM)的标准
- 这些内置对象的类型声明文件,就包含在TypeScript 核心库的类型声明文件中
11.5.1 使用jquery
//对于common.js风格的模块必须使用 import * as
import * as jQuery from 'jquery';
jQuery.ajax('/user/1');
复制代码
11.5.2 安装声明文件
cnpm i @types/jquery -S
复制代码
11.5.3 自己编写声明文件
types\jquery\index.d.ts
declare function jQuery(selector:string):HTMLElement;
declare namespace jQuery{function ajax(url:string):void
}
export default jQuery;
复制代码
tsconfig.json
- 如果配置了
paths
,那么在引入包的的时候会自动去paths
目录里找类型声明文件 - 在 webpack 中,我们可以通过配置 alias 的形式来为项目里的文件做映射。在
tsconfig.json
中,我们同样也可以做路径的映射 - 在 tsconfig.json 中,我们通过
compilerOptions
里的paths
属性来配置路径映射。 tsconfig.json{ "baseUrl": "./",// 使用 paths 属性的话必须要指定 baseUrl 的值 "paths": { "*":["types/*"] } 复制代码
11.5.4 npm声明文件可能的位置
- node_modules/jquery/package.json
- "types":"types/xxx.d.ts"
- node_modules/jquery/index.d.ts
- node_modules/@types/jquery/index.d.ts
11.6 扩展全局变量的类型
11.6.1 扩展局部变量类型
interface String {double():string;
}String.prototype.double = function(){return this+'+'+this;
}
console.log('hello'.double());interface Window{myname:string
}
console.log(window.myname);
//export {}
复制代码
11.6.2 模块内全局扩展
types\global\index.d.ts
declare global{interface String {double():string;}interface Window{myname:string}
}export {}
复制代码
"include": ["src/**/*","types/**/*"
]
复制代码
11.7 合并声明
- 同一名称的两个独立声明会被合并成一个单一声明
- 合并后的声明拥有原先两个声明的特性
- 类既可以作为类型使用,也可以作为值使用,接口只能作为类型使用
关键字 | 作为类型使用 | 作为值使用 |
---|---|---|
class | yes | yes |
enum | yes | yes |
interface | yes | no |
type | yes | no |
function | no | yes |
var,let,const | no | yes |
class Person{name:string=''
}
let p1:Person;//作为类型使用
let p2 = new Person();//作为值使用interface Animal{name:string
}
let a1:Animal;
let a2 = Animal;//接口类型不能用作值
复制代码
11.7.1 合并类型声明
- 可以通过接口合并的特性给一个第三方为扩展类型声明
use.js
interface Animal{name:string
}
let a1:Animal={name:'zhufeng',age:10};
console.log(a1.name);
console.log(a1.age);
复制代码
types\animal\index.d.ts
interface Animal{age:number
}
复制代码
11.7.2 使用命名空间扩展类
- 我们可以使用 namespace 来扩展类,用于表示内部类
class Form {username: Form.Item='';password: Form.Item=''; } //Item为Form的内部类 namespace Form {export class Item {} } let item:Form.Item = new Form.Item(); console.log(item); 复制代码
11.7.3 使用命名空间扩展函数
- 我们也可以使用
namespace
来扩展函数
function greeting(name: string): string {return greeting.words+name;
}namespace greeting {export let words = "Hello,";
}console.log(greeting('zhufeng'))
复制代码
11.7.4 使用命名空间扩展枚举类型
enum Color {red = 1,yellow = 2,blue = 3
}namespace Color {export const green=4;export const purple=5;
}
console.log(Color.green)
复制代码
11.8 生成声明文件 #
- 把TS编译成JS后丢失类型声明,我们可以在编译的时候自动生成一份JS文件
{"compilerOptions": {"declaration": true, /* Generates corresponding '.d.ts' file.*/}
}复制代码
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- ROSNOTE : dynamic reconfigure 动态调参
本文参考于:https://blog.csdn.net/u014610460/article/details/79531616#commentBox 目前官网给出的例程实现dynamic_reconfigure的客户端只给出了python例程,而服务端给了c和python两种方法的实现。 后来查看了下dynamic_reconfigure的源码ÿ…...
2024/4/21 13:26:26 - apollo-graphql 自己使用的一点姿势
apollo 能干什么 怎么用(react版) 2.1 引入方式// index.tsx import { LocaleProvider, message } from antd import zhCN from antd/lib/locale-provider/zh_CN; import { InMemoryCache } from apollo-cache-inmemory; import { ApolloClient } from apollo-client import {…...
2024/5/8 11:32:50 - Swagger结合mustache模板生成后台接口代码、以及前后台建模代码
之前项目中使用的的thrift来建模,维护前后台模型以及rest接口,前台使用的是angular2; 但是使用thrift只能生成建模,后台的rest接口的Controller文件还是需要手动去写,一旦接口改动就会涉及到很多方面。 由此准备使用S…...
2024/4/21 13:26:25 - 才割双眼皮一年了怎么还是不舒服
...
2024/4/21 13:26:24 - 【javascript】杂记
1.settimeout函数是指定毫秒数后调用函数或者是计算表达式的,而settimeout设置为0s,他被js放在队列中,要等别人执行完,他才会执行。 console.log(1); setTimeout(function(){console.log(2);},0); console.log(3);1 3 2 2 . nu…...
2024/4/21 13:26:22 - 松灵机器人Scout代码分析 --- scout_ros
公司采购了一款室外的四轮差速底盘,正在看通讯的代码。 代码的github: https://github.com/westonrobot/scout_ros scout_base_node.cpp 1. 调用 ScoutBase.h 的 connetc() : 设置通讯方式(serial or can )并 进行连接 2. scout_base/…...
2024/4/21 13:26:23 - [Javascript] 编程实践之1: Google的Javascript代码风格5:语言特性
Google的Javascript风格指南5 语言特性5.1 局部变量声明5.1.1 const和let的使用5.1.2 每次只声明一个变量5.1.3 仅在需要时声明,并且尽快初始化5.1.4 根据需要声明类型5.2 数组文法5.2.1 使用拖拽逗号5.2.2 不要使用可变数组的构造函数5.2.3 非数值性质5.2.4 析构5.…...
2024/4/20 15:57:51 - 平行眼割的双眼皮时间久了会成内双吗
...
2024/4/20 15:57:47 - 割双眼皮是不是时间越久
...
2024/4/20 15:57:47 - 双眼皮宽一点好还是窄一点好看
...
2024/5/9 3:58:41 - angular编译出错解决办法Angular Compiler was detected but it was an instance of the wrong class.
出现如下错误: Module build failed: Error: Angular Compiler was detected but it was an instance of the wrong class. This likely means you have several ngtools/webpack packages installed. You can check this with npm ls ngtools/webpack, and then…...
2024/5/8 17:03:21 - 拉双眼皮要价格多少钱
...
2024/4/20 15:57:43 - 拉双眼皮要价格多少钱啊
...
2024/4/29 10:40:44 - 刚做完双眼皮如何预防黏连
...
2024/4/20 15:57:41 - 双眼皮割的时间越长
...
2024/4/20 14:35:56 - 代码生成器 \ select2 \ 面包屑导航
1. 代码生成器 2. select2 (1) js 代码 /** * 数据格式 {data :[ ]} */ $scope.brandList{data:[{ id:1, text:联想 },{ id:2, text:华为},{ id:3, text:小米}]}; (2) html 页面 <link rel"stylesheet" href "../plugins/select2/select2.css"…...
2024/4/21 13:26:19 - 双眼皮几天线拆
...
2024/4/26 15:17:57 - 双眼皮线几天可以拆
...
2024/5/7 4:48:16 - 全切双眼皮两个月眼型不好看
...
2024/5/1 12:54:56 - SQL vs NoSQL 没有硝烟的战争!
SQL(结构化查询语言)数据库作为一个主要的数据存储机制已经超过40个年头了。随着web应用和像MySQL、PostgreSQL和SQLite这些开源项的兴起,SQL使用量大大增加。 NoSQL数据库在20世纪60年代就已经出现了,但最近因为MongoDB、CouchDB…...
2024/4/21 13:26:15
最新文章
- java 继承和静态属性或方法
目录 继承 静态属性和方法 继承与静态属性或方法的关系: 示例: 注意: PS:如有错漏之处,敬请指正 在Java中,继承和静态属性或方法是面向对象编程中的两个重要概念。它们在类设计和使用中扮演着不同的角…...
2024/5/9 5:10:27 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/7 10:36:02 - 【图论】知识点集合
边的类型 neighbors(邻居):两个顶点有一条共同边 loop:链接自身 link:两个顶点有一条边 parallel edges:两个顶点有两条及以上条边 无向图 必要条件:删掉顶点数一定大于等于剩下的顶点数 设无向图G<V,E>是…...
2024/5/7 21:13:52 - YOLOv9架构图分享
YOLOv9是YOLO (You Only Look Once)系列实时目标检测系统的最新迭代。它建立在以前的版本之上,结合了深度学习技术和架构设计的进步,以在目标检测任务中实现卓越的性能。通过将可编程梯度信息(PGI)概念与广义ELAN (GELAN)架构相结合,YOLOv9在…...
2024/5/6 12:36:11 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/8 6:01:22 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/7 9:45:25 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/9 4:20:59 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/7 11:36:39 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/6 1:40:42 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/8 20:48:49 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/7 9:26:26 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/8 19:33:07 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/5 8:13:33 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/8 20:38:49 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/6 21:42:42 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/4 23:54:56 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57