接下来,TypeScript我会简称为ts
1.预备环境:
安装node.js全局安装
typeScript:npm i -g typescript
2. 配置文件tsconfig.json
这里是ts编译器配置文件常用的配置项,该配置项在webpack也将使用,了解即可
{
/* ts 配置文件 */
// 哪些TS文件需要被编译
"include": [
// 根目录下src目录下任意目录的任意文件都会被编译
// ** 任意目录
// * 任意文件
"./src/**/*"
],
// 哪些TS文件不需要被编译
"exclude": [],
// 定义被继承的配置文件
// "extends": [],
// 编译哪些文件,写文件名,一般用不上
// "files": [],
// 编译器选项
"compilerOptions": {
// ts被编译的es版本
"target": "ES6",
// 指定使用模块化规范
"module": "amd",
// 指定项目中要使用的库,一般不用修改此配置
// "lib": ["DOM"]
// 指定编译后文件所在的目录
"outDir": "./dist",
// 将全局作用域代码合并为一个文件
"outFile": "./dist/app.js",
// 是否对js文件进行编译
"allowJs": false,
// 检查js代码是否符合语法规范
"checkJs": false,
// 是否移除注释
"removeComments": false,
// 不生成编译后的文件
"noEmit": false,
// 当有错误时不生成编译后的文件
"noEmitOnError": false,
// 设置编译后的文件使用严格模式
"alwaysStrict": true,
// 所有严格检查的总开关
// "strict": true,
// 不允许隐式any类型
"noImplicitAny": false,
// 不允许不明确的this
"noImplicitThis": true,
// 严格检查空值
"strictNullChecks": true
}
}
3. webpack打包ts
这里讲解简单搭建一个webpack打包环境,稍作了解即可。
1.段落引用生成webpack配置文件:npm init -y
2.段落引用下载webpack常用依赖:npm i -D webpack webpack-cli typescript
3.段落引用ts-loader根目录创建webpack配置文件:webpack.config.js,配置文件种编码如下:
const path = require('path')
module.exports = {
// 指定入口文件
entry: './src/index.ts',
// 指定打包文件所在目录
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
// 指定webpack打包时要使用的模块
module: {
// 指定加载规则
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node-modules/
}
]
},
mode: 'development'
}
4.创建ts配置文件 tsconfig.json #
5.在package.json添加脚本
"scripts": {
"build": "webpack"
}
一个简单的打包工具就这样构建好了,然后执行npm run build 就可以进行打包了
4. 使用vscode插件运行ts
该方式用来快速搭建一个ts运行环境,可以暂时不去接触各类打包工具,方便我们快速去尝试ts编程。
1.vscode安装run code插件
2.安装ts-node npm install -g ts-node
3.在.ts文件中右击选择 Run Code 即可运行当前文件的ts代码
5. 各种类型声明
类型声明,内容不多,请认真牢记,方便后续编写代码
let a: number
a = 10
a = 20
a = '123' // 会报错 不能将类型“string”分配给类型“number”
// 声明和赋值同时进行,会自动推断类型
let b = false
b = 123 // 会报错 不能将类型“number”分配给类型“boolean”
// 函数参数类型声明 返回值声明类型
function sum (a: number, b: number) : number {
return a + b
}
sum(1, '2') // 类型不对会报错
sum(1, 2) // 正确调用
// 字面量类型声明 联合类型
let c: 'apple' | 'orange' | 'banana'
let d: boolean | string | number
c = 'apple'
c = 'orange'
// c = 'dog' // 报错 不能将类型“"dog"”分配给类型“"apple" | "orange" | "banana"
// any类型可设置任何值
let e: any
e = 1
e = '1'
e = false
// unknown 未知类型
let f: unknown
f = 1
f = '1'
f = false
// any 和 unknown 的区别
// any可以赋值给任何变量,可能会影响其它变量的类型
// 断言:告诉编译器实际类型
let g = f as string // 变量 as 类型
let h = <string>g // <类型>变量
// void 表示空,如果用在函数,表示没有返回值
function fn (): void {
return undefined
}
// never 表示永远不会返回结果
function fn2 (): never {
throw new Error('报错了')
}
// 定义一个对象
let i: object
// 指定对象中可以包含哪些属性
let j: { name: string, age?: number } // 该对象只允许有name属性,可选属性是age
let k: { name: string, [propName: string]: any } // [propName: string]: any 表示任意属性
// 定义函数的类型和返回值类型
let l: (a: number, b: number) => number
// 定义一个数组
let m: string[]
let m1: Array<number>
m = ['1', '2', '3']
m1 = [1, 2, 3]
// 元组:固定长度的数组
let n: [string, string]
// 枚举:列举出所有可能性
enum Gender {
Male,
Female
}
let o: { name: string, gender: Gender }
o = {
name: '杨超越',
gender: Gender.Male
}
// 类型别名
type MyType = { name: string, gender: Gender }
let p: MyType
p = {
name: '杨超越',
gender: Gender.Male
}
6. 类(Class)
创建类通常的书写范式如下:
class 类名 {
属性名: 类型
constructor (参数: 类型) {
this.属性名 = 参数
}
方法名 () {
// do something
}
}
下面是个小栗子,包含类的属性、只读属性、静态属性和方法、构造函数。
class Person {
// 属性
name: string
age: number = 18
// 只读属性
readonly gender: string = '男'
// 定义静态属性
static weight: number = 120
// 构造函数 在对象创建时调用
constructor (name: string) {
this.name = name
}
// 定义方法
// 普通方法
sayHello (): void {
console.log('hello typescript')
}
// 静态方法
static sayHi (): void {
console.log('hi typescript')
}
}
const person = new Person('胡歌')
console.log(person.name) // 胡歌
console.log(person.age) // 18
console.log(person.gender) // 男
person.sayHello() // 'hello typescript
console.log(Person.weight) // 120
Person.sayHi() // hi typescript
7. 继承
ts中的继承和es6大同小异,看一下案例即可掌握。
class Animal {
name: string
age: number
constructor (name: string, age: number) {
this.name = name
this.age = age
}
say (): void {
console.log('animal speak')
}
}
class Dog extends Animal {
say (): void {
console.log('wang wang wang ~')
}
}
class Cat extends Animal {
// 如果子类加了构造函数
// 那么构造函数内必须调用一下父类构造函数
// super即可调用父类构造函数
constructor (name: string, age: number) {
super(name, age)
}
say (): void {
console.log('miao miao miao ~')
}
}
const dog = new Dog('旺财', 2)
const cat = new Cat('咪咪', 1)
dog.say() // wang wang wang ~
cat.say() // 'miao miao miao ~
8. 抽象类 and 抽象方法
如果不希望有人去实例化父类,那么可以用关键字 abstract 创建类,那这个类就是抽象类。
如果这个方法没有方法体,并用abstract 修饰,且只能写在抽象类中,且必须被子类重写,那这个方法就是抽象方法。
abstract class People {
name: string
age: number
constructor (name: string, age: number) {
this.name = name
this.age = age
}
// 定义抽象方法,没有方法体,只能写在抽象类中,且必须被子类重写
abstract say (): void
}
// const zhangsan = new People() // 会报错:无法创建抽象类的实例
9. 接口
接口可以当类型声明使用。
interface MyInterface {
name: string,
age: number
}
const obj: MyInterface = {
name: '222',
age: 18
}
接口也可以用来定义类的结构。
interface MyInter {
name: string,
speak (): void
}
class MyClass implements MyInter {
name: string
constructor (name: string) {
this.name = name
}
speak (): void {
console.log('hello ts')
}
}
总结一下,接口就是为了定义规范,对类进行限制以满足某种使用场景需求。
10. 属性修饰符
1.public 修饰属性可以在任意位置访问(默认)
2.private 私有属性 只能在类内部访问
3.protected 受保护的属性 只能在当前类和其子类中访问
4.get 设置getter方法
5.set 设置setter方法
class Person {
private name_: string
private age_: number
constructor (name: string, age: number) {
this.name_ = name
this.age_ = age
}
getString () {
return {
name: this.name_,
age: this.age_
}
}
// 设置getter方法
get name () {
return this.name_
}
// 设置setter方法
set name (value: string) {
this.name_ = value
}
}
const per = new Person('张三', 18)
// per.age // 错误的调用方式,会报错:属性“age”为私有属性,只能在类“Person”中访问
console.log(per.getString()) // { name: '张三', age: 18 }
per.name = '孙悟空'
console.log(per.name) // 孙悟空
11. 泛型
在定义函数或者类时,如果遇到类型不明确的情况可以使用泛型
在一个方法上使用泛型:
function fn<T> (a: T): T {
return a
}
fn<string>('hello')
fn<number>(10)
也可以指定多个泛型:
function fn2<T, K> (a: T, b: K): T {
console.log(b)
return a
}
fn2<number, string>(1, '2')
可以通过接口限制泛型:
interface Inter {
length: number
}
function fn3<T extends Inter> (a: T): number {
return a.length
}
fn3('123')
在类中定义泛型:
class MyClass<T> {
name: T
constructor (name: T) {
this.name = name
}
}
const mc = new MyClass<string>('张三')
© 著作权归作者所有
发表评论