准备工作:
本地写ts文件,要安装ts编译器: ts环境
npm i -g typescript
tsc -v
tsc hello.ts --------------> 生成对应.js文件
每次需要重新编译,再看效果,方法:安装ts-node包:npm i -g ts-node
手动编译执行:这个包在ts内部转换成js 直接执行js文件:
ts-node xx.ts -------> 直接运行ts文件
vscode自动编译ts:全局监听
创建tsconfig.json, 通过tsc --init 生成配置文件
打开注释outDir: './js'
(原理就是tsc -p d:\xxx --watch )
浏览器引用ts文件,时刻监听ts,实时刷新浏览器页面:
tsc xx.ts // tsc 生成js
页面引用js
tsc --watch xx.ts //实时监听这个文件变化
live serve 实时监听html页面变化-vscode插件
本地写ts文件,调试:-vscode
// vscode ts断点调试
// 第一步: 添加配置
// 第二步: 在当前目录下 npm i ts-node typescript 这2个包
原因:全局安装过不够 必须在当前目录下再安装一遍 才能运用到调试中。。。--巨坑!!!
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "chrome-htm", //运行html文件,用谷歌浏览器打开
"type": "chrome",
"request": "launch",
"url": "${file}",
"sourceMaps": true,
"webRoot": "${workspaceRoot}"
},
{
"name": "node-ts", //单独调试js,即可以直接运行js
"type": "node",
"request": "launch",
"args": ["${workspaceFolder}/hello.ts"], // 要调试的ts文件
"runtimeArgs": [ // 调试时 加载ts-node包 '直接'运行ts代码
"-r", "ts-node/register"
]
}
]
}
npm i ts-node typescript // 本地生成node-modules文件夹
打断点-点运行-进断点了!!!!
js是动态类型语言,typescript是静态类型语言,是js的超集。类型声明
所以ts文件内类型解析失败,也是可以tsc ts文件成js文件
tpyescript-类型声明:
1.基本类型声明:let a: 基本数据类型 = 基本数据
let a: number = 2 => let a = 2
function sum(a: numer, b: number): number {.........} sum(1, 2)
2.字面量:let a: 基本数据
let a: 2
3.联合类型: let a: string | number
let a: string | number
4.断言
let str:any
str as string
5.函数返回值 Void Never
Void表明函数内return了null/undefined
Never只要用来包裹报错函数的
6.对象的类型注解
let obj: {name: string; age: number; sayHi(): string}
对象的约束-interface
interface IUser {
name: string
sayHi: () => void
}
let obj1: IUser = {
name: '',
sayHi: () => {...}
}
7.enum 枚举 只读,不能set
enum Gender {
Male,
Female
}
let objPerson: Gender
objPerson = Gender.Female
------------node 环境:终端
node xx.js ----> 在cmd / 终端 中,直接执行js文件
tsc xx.ts -----> 在cmd中运行,终端不行:powershell禁止输入
WINDOWS 其他系统上叫terminal,比如mac上
cmd command line
\||/--升级版
powershell-文件夹中按住shift 鼠标右击 mac上在桌面上按command+空格,能弹出搜索框搜terminal/终端
cmd可以运行编译,vscode的终端中运行报错-tsc : 无法加载文件 C:\Users\MLH\AppData\Roaming\npm\tsc.ps1,因为在此系统上禁止运行脚本
因为powershell的执行策略改成RemoteSigned
https://www.jianshu.com/p/7a8ece1bba7f
------------- vscode 插件配置
// vscode 插件配置
1.设置快捷键log javascript.json
{
// Place your snippets for javascript here. Each snippet is defined under a snippet name and has a prefix, body and
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
// same ids are connected.
// Example:
"Print to console": {
"prefix": "log",
"body": [
"console.log('$1')",
"$2"
],
"description": "Log output to console"
}
}
2.设置html页面自动刷新 安装插件Live serve
3.vscode 窗口背景图 安装插件background setting.json
{
"workbench.iconTheme": "vscode-icons",
"eslint.codeAction.showDocumentation": {
// 设置 eslint 保存时自动修复
"eslint.autoFixOnSave": true,
},
"workbench.colorCustomizations": {
"terminal.background":"#292D3E",
"terminal.foreground":"#959DCB",
"terminalCursor.background":"#959DCB",
"terminalCursor.foreground":"#959DCB",
"terminal.ansiBlack":"#292D3E",
"terminal.ansiBlue":"#82AAFF",
"terminal.ansiBrightBlack":"#676E95",
"terminal.ansiBrightBlue":"#82AAFF",
"terminal.ansiBrightCyan":"#89DDFF",
"terminal.ansiBrightGreen":"#C3E88D",
"terminal.ansiBrightMagenta":"#C792EA",
"terminal.ansiBrightRed":"#F07178",
"terminal.ansiBrightWhite":"#FFFFFF",
"terminal.ansiBrightYellow":"#FFCB6B",
"terminal.ansiCyan":"#89DDFF",
"terminal.ansiGreen":"#C3E88D",
"terminal.ansiMagenta":"#C792EA",
"terminal.ansiRed":"#F07178",
"terminal.ansiWhite":"#959DCB",
"terminal.ansiYellow":"#FFCB6B"
},
"editor.tokenColorCustomizations": {
"editor.background": "#C792EA",
},
"terminal.integrated.automationShell.windows": "",
"terminal.integrated.shell.windows": "D:\\360Downloads\\tools\\Git\\git-cmd.exe",
"window.zoomLevel": 0,
"background.enabled": true,
"background.useDefault": false,
"background.customImages": [
"file:///D:/img.jpeg"
],
"background.style": {
"content": "''",
"pointer-events": "none",
"position": "absolute",
"z-index": "99999",
"width": "100%",
"height": "100%",
"background-position": "center",
"background-repeat": "no-repeat",
"background-size": "100%,100%",
"opacity": 0.2
},
"powermode.enabled": true,
"powermode.presets": "flames",
"backgroundCover.imagePath": "d:\\img.jpeg"
}
4.设置vscode断点配置 launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "chrome-htm", //运行html文件,用谷歌浏览器打开
"type": "chrome",
"request": "launch",
"url": "${file}",
"sourceMaps": true,
"webRoot": "${workspaceRoot}"
},
{
"name": "node-ts", //单独调试js,即可以直接运行js
"type": "node",
"request": "launch",
"args": ["${workspaceFolder}/hello.ts"],
"runtimeArgs": [
"-r", "ts-node/register"
]
}
]
}
5.直接运行ts代码 安装插件run code ,只是不能打断点
ts-类型:
number string boolean
array object function [参数-默认参数,可选参数,重载:参数不同走的方法不同]
tuple enum【会自动加1】
es5: 静态方法 Person.getInfo()直接调用 static定义的方法不能改变
实例方法 需要new再调用
构造函数实现继承的方法:es5
1.call(), 只能继承实例方法,不能继承实例方法外的原型链上的方法
2.原型链继承: Other.prototype = new Home()
// 继承 .call
function Home() { // 实例一
this.family = 'tom'
this.total = 8
this.sayHi = function () {
return 'hello~'
}
}
function Other() {
Home.call(this)
}
Home.prototype.run = function() {
return 'running'
}
// let home = new Home() 直接使用,不用造实例
let other = new Other()
other.sayHi()
other.run() // 报错,other.run is not a function
通过call方法实现的继承,不能继承此实例的原型链上的方法,只能继承实例上定义的方法和属性
// 原型链继承
function Home() { // 实例一
this.family = 'tom'
this.total = 8
this.sayHi = function () {
return 'hello~'
}
}
Home.prototype.run = function() {
return 'running'
}
function Fn1 () {}
Fn1.prototype = new Home()
let fn1 = new Fn1()
fn1.run() // running~
//缺点: 实例带参数
function Fn(name, age) {
this.name = name
this.age = age
this.run = function() {
return age +'岁的'+ name + '在running~'
}
}
function Fn4(name, age) {
// Fn.call(this, name, age)
}
Fn4.prototype = new Fn()
// 也可以 Fn4.prototype = Fn.prototype
let fn4 = new Fn4('tom', 20)
console.log('fn4-run', fn4.run()) // undefined 在running
用call+原型继承解决
构造函数实现继承: es6
// es6定义类
class Person {
public name: string;
constructor(n: string) { // 实例化时 触发的函数
this.name = n
}
run():void {
console.log(this.name + ' running~');
}
getName(): string {
return this.name
}
setName(v: string): void {
this.name = v
}
}
let p = new Person('tom')
p.run()
console.log(p.getName());
p.setName('cat')
console.log(p.getName());
// es6实现继承
class Table {
public name: string
constructor(n: string) {
this.name = n
}
run (): string {
return `${this.name}` + '在跑步..'
}
}
let table = new Table('tom')
console.log(table.run());
class Web extends Table{
constructor(name: string) {
super(name) // 初始化 父类的构造函数
}
}
let web = new Web('李四')
console.log(web.run());
es6 class类中修饰符
public: 类、子类、类外调用 都能访问
protected: 类、子类可调用,类外不能调用
private: 只在自己类内可调用
属性不加修饰符,默认就是公有-public
es6 class类中的静态属性 静态方法
// es6 中定义 静态属性 静态方法
class Bag {
public name: string
static name1: any = 'cat';
constructor(name: string) {
this.name = name
}
run(): string {
return `${this.name} 身上有个bag`
}
static work(): string {
return `${this.name1}在work`
}
}
let bag = new Bag('tom')
console.log(bag.run()); // 实例方法
console.log(Bag.name1); // 不通过new的方式,直接对象点访问的,叫静态属性
console.log(Bag.work()); // 方法属性
类的多态概念:
父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的实现/表现
多态属于继承,是继承的一种表现
// 多态: 父类不去实现,子类有不同的实现
class Car {
type: string
constructor(type: string) {
this.type = type
}
oil() {
}
}
class WeiLai extends Car{
constructor(type: string) {
super(type)
}
oil(): string {
return `${this.type}`
}
}
let weilai = new WeiLai('柴油')
console.log(weilai.oil());
class DaZhong extends Car{
constructor(type: string) {
super(type)
}
oil():string {
return `${this.type}`
}
}
let dazhong = new DaZhong('机油')
console.log(dazhong.oil());
ts抽象类: 规范子类,提供其他类的继承基类,不能被直接实例化
用 关键字abstract定义抽象类和抽象方法,
抽象类中的抽象方法不包含具体实现方法, 并且必须在派生类中实现
// 抽象方法 只存在于抽象类中
abstract class Car {
type: string
constructor(type: string) {
this.type = type
}
abstract oil(): any
}
class DaGi extends Car{
constructor(type: string) {
super(type)
}
oil(): string{
return this.type
}
}
console.log('------------------------------Car类中,要求派生类中必须包含oil这个方法');
let daGi = new DaGi('大G')
console.log(daGi.oil());
接口: 规范属性,方法,函数,可索引
Interface
abstract 定义子类的标准
// 属性类接口:函数参数的规范-接口
// 可批量使用interface
// 数组/对象类接口:
interface arrInter {
// index value => any类型
[index: number]: string
}
可使用: let arr: arrInter = ['name': 'tom']
也可使用: {...} as arrInter
// 类类型接口:对类的约束 和抽象类有点类似
interface Animal {
name: string
eat(): void
}
class Dog implements Animal { // implements 实施
name: string
constract(name: string) {
this.name = name
}
eat() {
console.log('dog吃肉肉')
}
}
let dog = new Dog('dog')
console.log(dog.eat())
//class 实现继承 + 类类接口继承
interface Person extends Animal {
work(): void
}
class Programer {
name: string
constructor(name: string) {
this.name = name
}
coding() {
console.log('coding-父类');
}
}
class Pwork extends Programer implements Person { // 重点!!
constructor(name: string) {// 重点!!
super(name)
}
eat() {
console.log('人类吃米饭');
}
work() {
console.log('人类工作');
}
money() {
return `${this.name}能花钱`
}
}
let p1 = new Pwork('人')
console.log(p1.eat(), p1.work(), p1.money(), p1.coding());
泛型: 传什么类型,返回什么类型
any:
():string {}
const fn: () => string = () => {return '111'}
// 泛型的定义 泛型函数
function getData<T>(value: T): T {
return value
}
getData<number>(1)
getData<string>('1')
function getData<T>(value: T): any {
return '1111'
}
getData(1)
getData("1")
// 泛型类
class Minclass<T> {
public list: T[] = []
add(v: T): void {
this.list.push(v)
}
min(): T {
let one = this.list[0]
for (let i: number = 0; i< this.list.length; i++) {
if (one > this.list[i]) {
one = this.list[i]
}
}
return one;
}
}
let min = new Minclass<number>()
min.add(2)
min.add(22)
min.add(12)
console.log(min.min());
let minstr = new Minclass<string>()
minstr.add('20')
minstr.add('22')
minstr.add('33')
console.log(minstr.min());
// 类作为参数约束传入的参数
class User {
public uname: string | undefined
public pwd: string | undefined
}
class MysqlDb {
add(user: User):boolean {
return true
}
}
// let mysqlDb = new MysqlDb()
// console.log(mysqlDb.add({uname: 'tom', pwd: '123'}));
let u = new User()
u.uname = 'tom'
u.pwd = '123'
let mDb = new MysqlDb()
console.log(mDb.add(u));
// 类作为参数约束传入的参数 -改成泛型: 避免代码重复+对不特定类型进行校验
// 泛型类 对传入的数据进行校验
class User {
public uname: string | undefined
public pwd: string | undefined
}
class MysqlDb<T> {
add(user: T):boolean {
console.log(user);
return true
}
}
// let mysqlDb = new MysqlDb()
// console.log(mysqlDb.add({uname: 'tom', pwd: '123'}));
let u = new User()
u.uname = 'tom'
u.pwd = '123'
let mDb = new MysqlDb<User>() // 类型校验是User
console.log(mDb.add(u));
// 给类分组 命名空间namespace
// x.ts
namespace A {
export class Aclass {....}
export let name = ...
}
namespace B {
export class Aclass {....}
export let name = ...
}
// 在内部使用:
let a = new A.Aclass()
let b = new B.Aclass()
.....
// 暴露出去
export namespace A {
export class Aclass {....}
export let name = ...
}
// 引用A
// 方法一
import { A } from 'x.ts'
let a = new A.Aclass()
...
// 方法二-不推荐
/// <reference path='x.ts' />
装饰器:对不改变类时的拓展
装饰器执行顺序:
属性 > 方法 > 方法参数 > 类
多个相同的装饰器,从后往前执行
// 装饰器
// 类装饰器 无参 传参-装饰器工厂
function deFn(p1: string) {
console.log('1--', p1);
return function(param: any) { // 装饰器工厂
console.log(param, '2--', p1);
param.prototype.name = '类装饰器'
param.prototype.otherName = p1
param.prototype.eat = () => {
console.log('类装饰器-eat')
}
}
}
// 紧贴着class 不能有分号
@deFn('tom') // -类装饰器表达式 会在运行时被当做函数调用, 类的构造函数作为其唯一的参数
class DeClass {
constructor() { // -类的构造函数
}
getData():void {
console.log('getData');
}
}
let de: any = new DeClass() // : any 去掉就报错
console.log(de.name);
de.eat()
de.getData()
console.log(de.otherName);
// 类装饰器 重载类构造器的属性和方法: 拓展或替换当前类[DeClass]的构造函数
function deFn(p1: string) {
return class extends DeClass { // 继承DeClass 一定要带上类的所有属性和方法,不然会报错
name: string = 'name重载'
getData(): void {
console.log('getData重载')
}
}
}
@deFn()
class DeClass {
public name: string | undefined
constructor() { // -类的构造函数
}
getData():void {
console.log('getData', this.name);
}
}
let de: any = new DeClass() // : any 去掉就报错
// 方法参数装饰器
function logParams(pas: any) {
// paramIndex 参数在参数数组中的下标
return function(target: any, methodNameA: any, paramIndex: number) {
console.log(target, methodNameA, paramIndex);
}
}
class AnimalFn {
@logAnimal('XXX-name')
public name: string | undefined
@logAnimal(20)
public age: number | undefined
constructor() {}
@logFn('methods')
getName(...any: any[]): void {
console.log('getName-我是', any)
}
// 方法参数装饰器
getDataA(@logParams('uuid') uuid: string): void {
console.log('logParams', uuid);
}
}
let aFn = new AnimalFn()
aFn.getName(12, 'xxx')
ts常见报错:
类型“DeClass”上不存在属性“name”:
-> let de: any = new DeClass()
let de = new DeClass()
console.log(de.name);
属性“age”没有初始化表达式,且未在构造函数中明确赋值:
-> public age: number | undefined
public age: number
已声明“target”,但从未读取其值
参数“target”隐式具有“any”类型:
-> function A (target: any){}
function A (target) {}
function A(target: any): typeof (Anonymous class)
作为表达式调用时,无法解析类修饰器的签名。
不能将类型“typeof (Anonymous class)”分配给类型“typeof Animal”。
Property 'getName' is missing in type '(Anonymous class)' but required in type 'Animal'.ts(1238)
decorator.ts(62, 5): 'getName' is declared here.
->
报错实例:
function A (target: any) {
console.log(target);
return class extends target {
name: any = '我是extends edit-name'
// constructor() {
// super()
// this.name = 'edit-name'
// }
// 解决-getName 也要重载一下
}
}
@A // error 红波浪线
class Animal {
public name: string | undefined
constructor() {
this.name = '我是构造函数animal -小动物'
}
getName() {
console.log('getName', this.name);
}
}
let animal = new Animal()
console.log(animal.name);
animal.getName()