tsc xxx.ts
1.生成配置文件tsconfig.json: tsc --init
2.修改tsconfig.json配置:
“outFirst”:''./js"
"strict":false
3.启动配置任务:
终端 --> 运行任务 --> 监视tsconfig.json
1.安装相关插件:
"clean-webpack-plugin": "^3.0.0",
"cross-env": "^7.0.2",
"html-webpack-plugin": "^4.5.0",
"ts-loader": "^8.0.11",
"typescript": "^4.0.5",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.2"
2.生成配置文件 (package.json tsconfig.json)
npm init -y
tsc init
3.修改配置文件 package.json
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js",
"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
},
4.新增 webpack.config.js(基本配置)
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')
const isProd = process.env.NODE_ENV === 'production' // 是否生产环境
function resolve(dir) {
return path.resolve(__dirname, '..', dir)
}
module.exports = {
mode: isProd ? 'production' : 'development',
entry: {
app: './src/main.ts',
},
output: {
path: resolve('dist'),
filename: '[name].[contenthash:8].js',
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
include: [resolve('src')],
},
],
},
plugins: [
new CleanWebpackPlugin({}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
resolve: {
extensions: ['.ts', '.tsx', '.js'],
},
devtool: isProd ? 'cheap-module-source-map' : 'cheap-module-eval-source-map',
devServer: {
host: 'localhost',
stats: 'errors-only',
port: 8081,
open: true,
},
}
5.运行/打包
npm run dev
npm run build
1.布尔型 Boolean
let isT:boolean=true
let isF:boolean=false
2.数字型 Number
let decLiteral: number = 6; //十进制
let hexLiteral: number = 0xf00d; //十六进制
let binaryLiteral: number = 0b1010;//二进制
let octalLiteral: number = 0o744;//八进制
3.字符串 String
let name:srting='eiton'
let sentence: string = `Hello, my name is ${ name }.`;
//模版字符串可以定义多行文本和内嵌表达式。 这种字符串是被反引号包围( `),并且以${ expr }这种形式嵌入表达式.
4.null 和 undefined (为其他类型的子类型)
// 两个空类型
let isUndefined: undefined = undefined
let isNull: null = null
// 常见区别
Number(null) // 0;
Number(undefined) // NaN
console.log(undefined == null) // ture
5.数组
// 某元素组成的数组 元素类型+[]
let numArr:number[] = [1,2,3]
// 数组泛型 Array<元素类型>
let numArr2:Array = [1,2,3]
6.元组 Tuple
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。
let arr: [string, number];
arr = ['hello', 10]; // OK
// arr = [10, 'hello']; // Error
7.枚举类型 Enum
枚举类型里的每个值都可称之为元素,每个元素均有编号(默认:从0开始,依次递增+1)
enum Color {Red=10, Green=20, Blue=30}
let green: Color = Color.Green; // 20
// 可以由枚举的值得到它的名字。 例如,我们知道数值为2,但是不确定它映射到Color里的哪个名字,我们可以查找相应的名字:
let colorName: string = Color[10];
8. Any类型
用于 在编程阶段还不清楚类型的变量指定一个类型
在ts中,any类型的变量跳过类型检查直接通过编译阶段的检查
但尽可能不要用到
let notSure: any = 4;// OK
notSure = "maybe a string instead";// OK
notSure = false;// OK
9.viod类型
// 表示函数没有返回值
function showMsg():void{
console.log('~~')
}
// 定义void变量,可接收undefined的值,但意义不大
let test:void = undefined
console.log(test)
10.object类型
function getObj(obj:object):object{
console.log(obj)
return {
name:'eiton',
age:18
}
}
console.log(getObj({str:'123'}))
console.log(getObj(new String('123')))
11.联合类型 Union Types
表示取值可以为多种类型中的一种
function getString(str:number|string):string{
return str.toString()
}
12.类型断言
语法1:<类型>值
语法2: 值 as 类型
function getString(str:number|string):number{
if((str).length){
return (str as String).length
}else{
return str.toString().length
}
}
13.类型推断
ts在没有明确指出类型时推断类型
情况1:定义时赋值,推断为对应的类型
情况2:定义时未赋值,推断为any类型
接口是对象的状态(属性)和行为(方法)的抽象(描述)
接口是一种类型,一种规范,一种规则,是一种能力,只一种约束
只读:readonly 属性:类型
非必须: 属性?:类型
// 需求:创建人的对象,需要对人的属性进行一定的约束
// id --- number类型 --- 必须 --- 只读
// name --- string类型 --- 必须
// age --- number类型 --- 必须
// sex --- string类型 --- 非必须
// 定义Iperson接口,用于限定或约束该对象中的属性数据
interface Iperson {
readonly id: number,
name: string,
age: number,
sex?: string
}
const person: Iperson = {
id: 1,
name: 'eiron',
age: 18,
sex: '女'
}
const person2: Iperson = {
id: 2,
name: 'hhy',
age: 18
}
console.log(person, person2)
为了使用接口表示函数类型,我们需要给接口定义一个调用签名。
它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。
interface Ifunct {
// 定义一个调用签名
(source: string, subString: string): boolean
}
const searchStr:Ifunct = function (source: string, subString: string): boolean {
// 查询
return source.search(subString) > -1
}
// 调用函数
console.log(searchStr('我有个摆烂的同事', '摆烂'))
类 类型:类的类型,类的类型可以通过接口实现
总结1:
类可以通过接口的方式,来定义当前这个类的类型
类可以实现一个接口,类也可以实现多个接口,要注意,接口中的内容都要真正的实现
总结2:
接口与接口之间叫继承(使用的是extends关键字),类和接口之间叫实现(使用的是 implements 关键字)
// 定义一个接口
interface Ifly {
// 改方法没有任何的实现(方法中什么也没有)
fly()
}
// 定义一个类 ,类的类型是上面定义的接口(可理解为 Ifly接口约束了当前的Person类)
class Person implements Ifly {
// 实现接口中的方法
fly() {
console.log('我会飞了~')
}
}
// 实例化对象
const person = new Person()
person.fly()
// 定义一个接口
interface ISwim {
// 改方法没有任何的实现(方法中什么也没有)
swim()
}
// 定义一个类 ,类的类型是上面定义的接口(可理解为 Ifly接口约束了当前的Person类)
class Person2 implements Ifly, ISwim {
// 实现接口中的方法
fly() {
console.log('我会飞了~')
}
swim() {
console.log('我会游泳了~')
}
}
// 实例化对象
const person2 = new Person2()
person2.fly()
person2.swim()
// 接口可以继承其他的多个接口
interface IFlyAndSwim extends Ifly, ISwim {
}
class Person3 implements IFlyAndSwim {
// 实现接口中的方法
fly() {
console.log('我会飞了~')
}
swim() {
console.log('我会游泳了~')
}
}
const person3 = new Person3()
person3.fly()
person3.swim()
可以理解为模板,通过模板可以实例化对象
是面向对象的编程思想
// ts中类的定义及使用
class Person {
// 定义属性
name: string
age: number
gender: string
// 定义构造函数:为了将来实例化对象的时候,可以直接对属性值进行初始化
constructor(name: string = "eiton", age: number = 18, gender: string = '女') {
this.name = name
this.age = age
this.gender = gender
}
// 定义实例方法
sayHi(str: string) {
console.log(`hello everybody~!我是${this.name},今年${this.age},是个${this.gender}孩子`, str)
}
}
// ts中使用类,实例化对象,可以直接进行初始化操作
const person = new Person()
person.sayHi('很高兴认识你们~!');
const person2 = new Person('噸噸坚', 25, '男')
person2.sayHi('很高兴认识你们~!');
继承:类与类之间的一种关系
举例:a类继承了b类,那么,a类为子类(派生类),b类为基类(超类/父类)
总结:
(()->{
// 定义一个类作为基类(父类/超类)
class Person {
name: string
age: number
gender: string
// 定义构建函数
constructor(name: string = 'eiton', age: number = 18, gender: string = '女') {
this.name = name
this.age = age
this.gender = gender
}
// 定义实例方法
sayHi(str: string): void {
console.log(`我是${this.name},今年${this.age},${str}`)
}
}
// 定义一个类,继承自Person
class Student extends Person {
constructor(name: string, age: number, gender: string) {
// 调用父类中的构造函数,使用的是super
super(name, age, gender)
}
// 调用父类中的方法
sayHi() {
console.log('Student类中的sayHi方法')
super.sayHi('很高兴认识你~!')
}
}
// 实例化 Person
const person = new Person('peach', 22, '女')
person.sayHi('啦啦啦~');
// 实例化 Student
const student = new Student('胖噸噸', 26, '男')
student.sayHi();
})()
多态:父类型的引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为。
// 定义一个父类
class Animal {
name: string
constructor(name: string) {
this.name = name
}
callEvent(sound: string = '嗷呜呜') {
console.log(`我是一只${this.name},${sound}`)
}
}
// 定义一个子类
class Dog extends Animal {
constructor(name: string) {
// 调用父类的构造函数,实现子类中属性的初始化操作
super(name)
}
// 实例方式,重写父类中的实例方法
callEvent(sound: string = '汪汪') {
console.log(`我是一只${this.name},${sound}`)
}
}
// 定义一个子类
class Cat extends Animal {
constructor(name: string) {
// 调用父类的构造函数,实现子类中属性的初始化操作
super(name)
}
// 实例方式,重写父类中的实例方法
callEvent(sound: string = '喵喵') {
console.log(`我是一只${this.name},${sound}`)
}
}
// 实例化父类对象
const ani: Animal = new Animal('动物')
ani.callEvent('嗷呜~')
// 实例化Dog类对象
const dog: Dog = new Dog('旺财')
dog.callEvent()
// 实例化Cat类对象
const cat: Cat = new Cat('来福')
cat.callEvent()
console.log('----')
// 父类和子类的关系:父子关系,此时,父类类型可以创建子类的对象
const dog1: Animal = new Dog('招娣')
dog1.callEvent()
const cat1: Animal = new Cat('顺水')
cat1.callEvent()
//
function showSound(ani: Animal) {
ani.callEvent()
}
console.log('----')
showSound(dog1)
showSound(cat1)
修饰符(类中成员的修饰符):用于描述类中成员(属性,构造函数,实例方法)的可访问性
类中成员的默认修饰符为public
public:公共的,任何位置均可访问
private:私有的,仅能在类中才可访问,子类也无法访问
protected:受保护的,仅可在类、子类中访问
class Person {
// 定义属性
public name: string
private age: number
protected gender: string
// 定义构造函数:为了将来实例化对象的时候,可以直接对属性值进行初始化
constructor(name: string = "eiton", age: number = 18, gender: string = '女') {
this.name = name
this.age = age
this.gender = gender
}
// 定义实例方法
public sayHi(str: string) {
console.log(`hello everybody~!我是${this.name},今年${this.age},是个${this.gender}孩子`, str)
}
}
// ts中使用类,实例化对象,可以直接进行初始化操作
const person = new Person()
// 类的外部可以访问类的属性,实例方法
console.log(person.name)
// console.log(person.age) //err
// console.log(person.gender) //err
person.sayHi('很高兴认识你们~!');
readonly:仅读的,不可修改的。
构造函数中,可对仅读的属性成员的数据进行修改
构造函数中的参数可被readonly修饰,修饰后的该类中就有了这个只读属性,该属性可被外部访问,但不能修改。
构造函数中的参数可被public、private、protected修饰,修饰后的该类会自动添加这个属性成员
class Person {
// 定义属性
readonly name: string
// 定义构造函数:为了将来实例化对象的时候,可以直接对属性值进行初始化
constructor(name: string) {
this.name = name
this.name = ‘哈哈’ // 可以,但意义不大
}
// 定义实例方法
public sayHi(str: string) {
// this.name = str // err
}
}
let person:Person = new Person('小甜甜')
console.log(person.name) //小甜甜
//person.name = '小怪兽' // err
通过getters(get)和setters(set),有效的控制对对象成员的访问
class Employee {
firstName: string
lastName: string
constructor(firstName: string, lastName: string) {
this.firstName = firstName
this.lastName = lastName
}
// 姓氏和名字的成员属性(外部可以访问,也可以修改)
// 读取器
get fullName() {
return this.firstName + '_' + this.lastName
}
// 设置器
set fullName(str) {
let nameArr = str.split('_')
this.firstName = nameArr[0] || ''
this.lastName = nameArr[1] || ''
}
}
const emp: Employee = new Employee('Chen', 'Eiton')
console.log(emp.fullName)
emp.fullName = '黄_噸噸'
console.log(emp)
在类中通过static修饰的属性或方法,称之为静态属性或静态方法。总称为静态成员。(构造函数不能通过static来修饰)
可以通过类名. 来调用静态成员
class Person {
// 静态属性
static name1: string = '小甜甜'
constructor() {
// 此时 this 指的是实例对象,name1为静态属性,不能通过实例对象直接调用静态属性来使用
// this.name1 = name
}
static sayHi(str: string = 'hello~!') {
console.log(str)
}
}
const person: Person = new Person()
// 通过实力对象调用的属性和方法
// console.log(person.name1) // 属性
// person.sayHi(); // 方法
// 通过 类名. 来访问静态属性 (可以读取,可以修改)
console.log(Person.name1)
Person.name1 = '啦啦啦~'
console.log(Person.name1)
// 通过 类名. 来调用静态方法
Person.sayHi(); // 方法
抽象类包含抽象方法(抽象方法一般没有任何具体内容实现),也可以包含实例方法,抽象类是不能被实例化的。
抽象类的最终目的(作用)是为子类(派生类)服务
// 定义一个抽象类
abstract class Animal {
// 抽象属性
abstract name: string
// 抽象方法
abstract eatEvent()
// 抽象方法不能有具体的实现
// abstract eatEvent() {
// console.log('真好吃~!')
// } //err
// 实例方法
callEvent() {
console.log('啦啦啦啦~')
}
}
// 抽象类不能被实例化
// const ani:Animal=new Animal() //err
// 定义一个子类(派生类)
class Dog extends Animal {
name: string = '噸噸'
eatEvent() {
console.log('吃狗粮~!')
}
}
// 实例化 Dog 类
const dog: Dog = new Dog()
dog.eatEvent()
// 调用抽象类中的实例方法
dog.callEvent()
console.log(dog.name)
函数:封装重复率高的代码,在使用时直接调用。
// 函数声明 命名函数
function add(x: number, y: number): number { //求和函数
return x + y
}
// 函数表达式 匿名函数
const add2 = function (x: number, y: number): number {
return x + y
}
// 函数的完整写法
const add: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y
}
console.log(add(1, 2))
// 可选参数:函数声明时,内部参数由 ? 修饰的参数(即可传可不传)。
// 默认参数:函数声明时,内部参数存在默认值的参数。
const fullName: (firstName: string, lastName?: string) => string = function (firstName: string, lastName?: string): string {
if (lastName) {
return firstName + '_' + lastName
} else {
return firstName
}
}
console.log(fullName('Chan', 'Eiton'))
console.log(fullName('Chan'))
// 剩余参数
// ...args:string[]表示:剩余的参数放在了字符串数组中
function showMsg(str: string, ...args: string[]) {
console.log(str) // aa
console.log(args) //["bb", "cc"]
}
showMsg('aa', 'bb', 'cc')
函数重载
函数重载:函数名相同,函数参数及个数不同。
// 函数重载声明
function plus(x: string, y: string): string
function plus(x: number, y: number): number
// 函数声明
function plus(x: string | number, y: string | number): string | number {
if (typeof x === 'string' && typeof y === 'string') {
return x + y
} else if (typeof x === 'number' && typeof y === 'number') {
return x + y
}
return '啥也不是'
}
console.log(plus('a', 'b'))
console.log(plus(1, 2))
// console.log(plus('a', 2)) //err 添加 函数重载声明后,遇见非法参数"报红"
在定义函数、接口、类时,不能预先确定要使用的数据的类型,而是在使用时才能确定的类型
单个泛型参数
function getArr(value: T, count: number): T[] {
// const arr:T[]=[]
const arr: Array = []
for (let i: number = 0; i < count; i++) {
arr.push(value)
}
return arr
}
const arr1 = getArr(100.123, 3)
console.log(arr1)
console.log(arr1[0].toFixed(1))
const arr2 = getArr('aaa', 3)
console.log(arr2)
console.log(arr2[0].split(''))
// 多个泛型参数
function getMsg(value1: K, value2: V): [K, V] {
return [value1, value2]
}
const msg = getMsg(12, 'aaa')
console.log(msg)
在定义接口时,为接口中的属性或方法定义泛类类型,在使用接口时,再指定具体的泛型类型。
// 接口中的泛型
interface IBaseCURD {
data: Array
add: (t: T) => T
getUserId: (id: number) => T
}
class User {
id?: number
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
class UserCRUD implements IBaseCURD {
data: Array = []
add(user: User): User {
user.id = Date.now() + Math.random()
this.data.push(user)
return user
}
getUserId(id: number): any {
console.log("输出this.data", this.data)
console.log(this.data.find(user => user.id === id));
return this.data.find(user => user.id === id)
}
}
const userCRUD: UserCRUD = new UserCRUD()
userCRUD.add(new User('jeck', 22))
let { id } = userCRUD.add(new User("eson", 30))
userCRUD.add(new User("luck", 25))
userCRUD.add(new User("may", 22))
console.log(userCRUD.data);
console.log(id);
typeof id == 'number' ? console.log("查找成功", userCRUD.getUserId(id)) : console.log("查找失敗");
定义一个类,类中的属性值的类型不确定,方法中的参数及返回值的类型也不确定
注:number和Number、string和String 是不一样的
// 泛型类
class className{
defaultValue: T
constructor(defaultValue: T) {
this.defaultValue = defaultValue
}
add: (x: T, y: T) => T
}
const obj1: className = new className(100)
obj1.add = function (x, y) {
return x + y
}
obj1.add(8, 8)
const obj2: className = new className('aaa')
obj2.add = function (x, y) {
return x + y
}
obj2.add('sef', '?')
// 泛型约束
// 定义一个接口 用于约束
interface ILen {
length: number
}
function getLen(x: T): number {
return x.length
}
console.log(getLen('hello everybody~'))
//console.log(getLen(123)) // err:Type 'number' does not satisfy the constraint 'ILen'.
// // 1.安装 jq 插件 npm install jquery
// // 2.引入第三方库 jq
// import jQuery from 'jQuery'
// // 3.定义操作
// declare var jQuery: (selector: string) => any // 一般定义会放在 jQuery.d.ts 文件(自动扫描,不需引入)中
// // 4.使用 jq
// jQuery('选择器')
// // 将 定义会放在 jQuery.d.ts 文件(自动扫描,不需引入)中
// jQuery('选择器')
/*
当时用第三方库时,我们需要引入它的声明文件,才能获得对应的代码补全、接口提示等功能;
声明语句:如果需要ts对新的语法进行检查,需要加载了对应的类型说明代码
declare var jQuery: (selector: string) => any
声明文件:吧声明语句方式单独的文件中( jQuery.d.ts ),ts会自动解析到项目中所有声明文件
下载声明文件:npm install @types/jquery --save-dev
*/
// 下载声明文件后
import jQuery from 'jQuery'
jQuery('选择器')
ECMAScript 的内置对象
// ECMAScript 的内置对象
let b: Boolean = new Boolean(1)
let n: Number = new Number(true)
let s: String = new String('abc')
let d: Date = new Date()
let r: RegExp = /^1/
let e: Error = new Error('error message')
b = true
// let bb: boolean = new Boolean(2) // error
BOM 和 DOM 的内置对象
// BOM 和 DOM 的内置对象
const div: HTMLElement = document.getElementById('test')
const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
console.dir(event.target)
})
const fragment: DocumentFragment = document.createDocumentFragment()