极速上手TypeScript应用
简介
- TypeScript是JavaScript的超集。
- 它对JS进行了扩展,向JS中引入了类型的概念,并添加了许多新的特性。
- TS代码需要通过编译器编译为JS,然后再交由JS解析器执行。
- TS完全兼容JS,换言之,任何的JS代码都可以直接当成JS使用。
- 相较于JS而言,TS拥有了静态类型,更加严格的语法,更强大的功能;TS可以在代码执行前就完成代码的检查,减小了运行时异常的出现的几率;TS代码可以编译为任意版本的JS代码,可有效解决不同JS运行环境的兼容问题;同样的功能,TS的代码量要大于JS,但由于TS的代码结构更加清晰,变量类型更加明确,在后期代码的维护中TS却远远胜于JS。
安装
-
下载Node.js
- 64位:https://nodejs.org/dist/v14.15.1/node-v14.15.1-x64.msi
- 32位:https://nodejs.org/dist/v14.15.1/node-v14.15.1-x86.msi
-
安装Node.js
-
使用npm全局安装typescript
- 进入命令行
- 输入:npm i -g typescript
-
创建一个ts文件
-
使用tsc对ts文件进行编译
- 进入命令行
- 进入ts文件所在目录
- 执行命令:tsc xxx.ts
基本类型
类型 | 例子 | 描述 |
---|---|---|
number | 1, -33, 2.5 | 任意数字 |
string | 'hi', "hi", hi |
任意字符串 |
boolean | true、false | 布尔值true或false |
字面量 | 其本身 | 限制变量的值就是该字面量的值 |
any | * | 任意类型 |
unknown | * | 类型安全的any |
void | 空值(undefined) | 没有值(或undefined) |
never | 没有值 | 不能是任何值 |
object | {name:'孙悟空'} | 任意的JS对象 |
array | [1,2,3] | 任意JS数组 |
tuple | [4,5] | 元素,TS新增类型,固定长度数组 |
enum | enum{A, B} | 枚举,TS中新增类型 |
TS的类型声明
作用
类型声明可以指定TS中变量(参数、形参)的类型
给变量设置了类型,使得变量只能存储某种类型的值
当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错
语法
let 变量: 类型; let 变量: 类型 = 值; function fn(参数: 类型, 参数: 类型): 类型{ ... }
字面量赋值
使用字面量进行类型声明,限制只能是声明的字面量,赋值其它值编译报错
let a: 10;
a = 10;
可以使用 | 来连接多个类型(联合类型),限制只能是其中一个字面量,赋值其它值编译报错
let b: "male" | "female";
b = "male";
b = "female";
void
用来表示空,以函数为例,就表示没有返回值的函数
function fn(): void{
}
unknown
表示未知类型的值,类型安全的any,unknown类型不能直接赋值给其它类型
let e: unknown;
e = "some test";
let s:string;
s = e; //报错
s = e as string; // 编译器不处理,手动声明后不报错,编译通过
s = <string> e; // 另一个语法形式
never
表示永远不会返回结果
function fn2(): never{
throw new Error('报错了!');
}
object
语法:{属性名:属性值,属性名:属性值}
[propName: string]: any 表示任意类型的属性
let c: {name: string, [propName: string]: any}; c = {name: '猪八戒', age: 18, gender: '男'};
数组
// string[] 表示字符串数组 let e: string[]; e = ['a', 'b', 'c']; // number[] 表示数值数值 let f: number[]; let g: Array<number>; g = [1, 2, 3];
元组
元组就是固定长度的数组
let h: [string, number];
h = ['hello', 123];
枚举
enum Gender{
Male,
Female
}
let i: {name: string, gender: Gender};
i = {
name: '孙悟空',
gender: Gender.Male // 'male'
}
类型断言
可以用来告诉解析器变量的实际类型
s = e as string;
s = <string>e;
生成 tsconfig.json
tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译
$ tsc -v
如果版本大于1.6,则需要更新:
$ npm install -g typescript
请记住,需要安装node.js才能使用npm。
正确的命令--init
不是init
:
$ tsc --init
默认生成的内容
{ "include": ["*"], //定义希望被编译文件所在的目录 "exclude": ["./src/hello/**/*"],// 默认值:["node_modules", "bower_components", "jspm_packages"] "compilerOptions": { /* Visit https://aka.ms/tsconfig.json to read more about this file */ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es5", /* 设置ts代码编译的目标版本 Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* 设置编译后代码使用的模块化系统 Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* 是否对js文件编译 Allow javascript files to be compiled. */ // "checkJs": true, /* 是否对js文件进行检查 Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* 将所有的文件编译为一个js文件 Concatenate and emit output to single file. */ // "outDir": "./", /* 编译后文件的所在目录 默认情况下,编译后的js文件会和ts文件位于相同的目录,设置outDir后可以改变编译后文件的位置 Redirect output structure to the directory. */ // "rootDir": "./", /* 指定代码的根目录,默认情况下编译后文件的目录结构会以最长的公共目录为根目录,通过rootDir可以手动指定根目录Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "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'. */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ "strict": true, /* 启用所有的严格检查,默认值为true,设置后相当于开启了所有的严格检查 Enable all strict type-checking options. */ // "noImplicitAny": true, /* 禁止隐式的any类型 Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* 严格的空值检查 Enable strict null checks. */ // "strictFunctionTypes": true, /* 严格检查函数的类型 Enable strict checking of function types. */ // "strictBindCallApply": true, /* 严格检查bind、call和apply的参数列表 Enable strict 'bind', 'call', and 'apply' methods on functions. */ // "strictPropertyInitialization": true, /* 严格检查属性是否初始化 Enable strict checking of property initialization in classes. */ // "noImplicitThis": true, /* 禁止类型不明确的this Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* 总是以严格模式对代码进行编译 Parse in strict mode and emit "use strict" for each source file. */ /* 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, /* 检查switch语句包含正确的break Report errors for fallthrough cases in switch statement. */ // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "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. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ /* Advanced Options */ "skipLibCheck": true, /* Skip type checking of declaration files. */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ } }
常用配置
{ "include": [ "./src/**/*" ], "compilerOptions": { "target": "es2015", "module": "es2015", // outDir 用来指定编译后文件所在的目录 "outDir": "./dist", // 将代码合并为一个文件 // 设置outFile后,所有的全局作用域中的代码会合并到同一个文件中 //"outFile": "./dist/app.js" // 是否对js文件进行编译,默认是false // "allowJs": true, // 是否检查js代码是否符合语法规范,默认是false // "checkJs": true, // 是否移除注释 "removeComments": true, // 不生成编译后的文件 "noEmit": false, // 当有错误时不生成编译后的文件 "noEmitOnError": true, // 所有严格检查的总开关 "strict": true, // 用来设置编译后的文件是否使用严格模式,默认false "alwaysStrict": true, // 不允许隐式的any类型 "noImplicitAny": true, // 不允许不明确类型的this "noImplicitThis": true, // 严格的检查空值 "strictNullChecks": true } }
面向对象
封装
- 对象实质上就是属性和方法的容器,它的主要作用就是存储属性和方法,这就是所谓的封装
- 默认情况下,对象的属性是可以任意的修改的,为了确保数据的安全性,在TS中可以对属性的权限进行设置
- 如果在声明属性时添加一个readonly,则属性便成了只读属性无法修改
权限
- public(默认值),可以在类、子类和对象中修改
- protected ,可以在类、子类中修改
- private ,可以在类中修改
构造函数
class Animal{ name: string; age: number; constructor(name: string, age: number){ this.name = name; this.age = age; } }
GETTER/SETTER
- 直接将其设置为private将导致无法再通过对象修改其中的属性
- 我们可以在类中定义一组读取、设置属性的方法,这种对属性读取或设置的属性被称为属性的存取器
- 读取属性的方法叫做setter方法,设置属性的方法叫做getter方法
静态属性
- 静态属性(方法),也称为类属性。使用静态属性无需创建实例,通过类即可直接使用
- 静态属性(方法)使用static开头
继承
- 继承时面向对象中的又一个特性
- 通过继承可以将其他类中的属性和方法引入到当前类中
抽象类
- 抽象类是专门用来被其他类所继承的类,它只能被其他类所继承不能用来创建实例
- 使用abstract开头的方法叫做抽象方法,抽象方法没有方法体只能定义在抽象类中,继承抽象类时抽象方法必须要实现
this/super
- 在类中,使用this表示当前对象
- 在类中,使用super表示父类对象
接口
接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。
interface Person{ name: string; sayHello():void; } function fn(per: Person){ per.sayHello(); } fn({name:'孙悟空', sayHello() {console.log(`Hello, 我是 ${this.name}`)}});
实现接口
interface Person{ name: string; sayHello():void; } class Student implements Person{ constructor(public name: string) { } sayHello() { console.log('大家好,我是'+this.name); } }
泛型
定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时泛型便能够发挥作用。
函数泛型
function test<T>(arg: T): T{ return arg; }
类泛型
class MyClass<T>{ prop: T; constructor(prop: T){ this.prop = prop; } }
多个泛型
多个泛型使用逗号隔开
function test<T, K>(a: T, b: K): K{ return b; } test<number, string>(10, "hello");
泛型约束
使用T extends MyInter
表示泛型T必须是MyInter的子类,不一定非要使用接口类和抽象类同样适用。
interface MyInter{ length: number; } function test<T extends MyInter>(arg: T): number{ return arg.length; }