https://coding.imooc.com/learn/list/412.html
 公司花钱买的,我边学边做笔记
设置
vscode设置

 然后下个Prettier - Code formatter
 
 
 
 以后保存就能格式化了
下载ts
npm install typescript@3.6.4 -g ts版本
 npm install -g ts-node@8.4.1 node执行ts文件
 这样,以后就能
//demo.ts
console.log(123);
PS D:\touchFish\code\typeScript> ts-node.cmd .\demo.ts
123
一些类型?
// 基础类型就布兰、字符、数值就不一一列出
// 对象类型
const func1 = (str: string) => {
    return parseInt(str)
}
// 自定义对象类型
interface Person {
    name: string
}
const p: Person = {
    name: 'jack'
}
// 泛型类型?
let temp: number | string = 123;
temp = '456'
然后interface、class、type这3个写法都差不多?不知道区别是啥,不像java分那么细
元组
长度和类型都固定的数组
const tuple: [string, string, number] = ['a', 'b', 1]
interface
interface Person{
    // private 
    readonly name:string;
    // 可有可无的属性
    age?:number;
    // 允许有其他的属性
    [propName:string]:any;    
    // 要有个函数,返回类型为string
    say():string;
}
然后一样像Java,interface可以被interface 继承extends
 然后class一样可以implementsinterface
 interface一样地,只是写而没有实际地方法内容之类的,要在class中写
class
老Java了
// public 公共
// private 私有
// protected 允许类内和子类使用
class Person {
    public name: string;
    private age: number;
    protected sayHi() {
        this.name; //使用共有
        this.age; //允许类内使用
        console.log('hi');
    }
}
class Teacher extends Person {
    public say() {
        this.sayHi() //允许类内使用
        this.name
        // this.age//私有,读不了
    }
}
const T = new Teacher()
// console.log(T.sayHi());//访问不了,因为sayHi是protected,只允许类内和子类使用
构造器
老Java了
class Person {
    constructor(public name: string) { }
}
class Teacher extends Person {
    constructor(public name: string, public age: number) {
        super(name)
    }
}
const teacher = new Teacher('tom', 12);
get和set
老Java了
static单例模式
老Java了
class Person {
    private constructor(public name: string) { }
    static createObj(name: string) {
        return new Person(name)
    }
}
const p = Person.createObj('啊强')
console.log(p.name);
抽象类
老java了
ts文件使用js类的包
比如在ts中npm install js的包,会导致不识别,这时候可以再进行
 npm install @types/xxx -D
 这个相当于
ts —> xxx.d.ts (翻译文件,用于ts识别js) --> js
ts的文件配置
tsc --init
生成一个tsconfig.json文件,
 顺便说,npm init -y可以生成package.json
 
 很明显嘛,一些json,都是配置项,下面跟着视频用一些简单的配置
tsc
创建个文件,test.ts,
class A {
    name: string
    constructor(name: string) {
        this.name = name
    }
}
const asdasd = new A('aaa')
console.log(asdasd.name);
然后tsc,就会自动编译成js嘛
//test.js
"use strict";
var A = /** @class */ (function () {
    function A(name) {
        this.name = name;
    }
    return A;
}());
var asdasd = new A('aaa');
console.log(asdasd.name);
tsc就是自动将根目录的ts转变为js,
 如果多个ts,但只想编译其中某几个,就可以再tsconfig.json中配置
{
  "include":["./test.ts"],
}
热更新
tsc -w
输出为单文件
这里是一个ts生成一个js,但也可以只生成一个js,只要设置
   "outFile": "./dist/page.js",                       /* Concatenate and emit output to single file. */
类型保护方式
class Bird {
    sing: () => {};
}
class Dog {
    bark: () => {};
}
// as 来做保护
function tarin(animal: Bird | Dog) {
    (animal as Bird).sing;
    (animal as Dog).bark;
}
// in来做保护
function tarin2(animal: Bird | Dog) {
    if ('sing' in animal) {
        animal.sing();
    } else {
        animal.bark();
    }
}
class NumberObj {
    count: number;
}
// instanceof来做保护
function add(first: object | NumberObj, second: object | NumberObj) {
    if (first instanceof NumberObj && second instanceof NumberObj) {
        return first.count + second.count;
    }
    return 0;
}
枚举
enum Status{
    OFF,
    ON,
    DELETE
}
console.log(Status);
console.log(Status.OFF);
console.log(Status[0]);
{ ‘0’: ‘OFF’, ‘1’: ‘ON’, ‘2’: ‘DELETE’, OFF: 0, ON: 1, DELETE: 2 }
0
OFF
泛型
function join<T>(first: T, second: T) {
    return `${first}${second}`;
}
const res = join<String>('1', '2')
console.log(res);
12
命名空间namespace
其实就是把类统筹到一起,叫做命名空间namespace
 比如
//这有一个命名空间,有2个类
namespace Components {
    export class Header {
        constructor() {
            console.log('I am Header');
        }
    }
    export class Content {
        constructor() {
            console.log('I am Content');
        }
    }
}
//这有另一个命名空间,下面这段话相当于import引入的写法
///<reference path="Components.ts"/>
namespace Home {
    export class Page {
        constructor() {
            new Components.Content();
            new Components.Header();
        }
    }
}
然后我们设置打包
{
  "compilerOptions": {
    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
    "module": "amd",    //只支持amd或者system                 /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "outFile": "./dist/page.js",     //输出单文件                  /* Concatenate and emit output to single file. */
    "outDir": "./dist",       //输出文件                 /* Redirect output structure to the directory. */
    "rootDir": "./src",      //要打包的文件                 /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    "strict": true,            
    "esModuleInterop": true                  
  }
}
导出来的js

装饰器
这和java的注解很是相似
 要先开启tsconfig.json的
{
  "compilerOptions": {
    "experimentalDecorators": true,       
    "emitDecoratorMetadata": true,        
  }
}
function Path(target: any) {
    console.log('我是装饰器');
}
function PathParam(str1: string, str2: string) {
    return function (target: any) {
        console.log(str1 + str2);
    }
}
@Path
class Test { }
@PathParam('hello', 'world')
class Test2 { }
ts-node跑一下
我是装饰器
helloworld
方法的装饰器
// 普通方法:target对应类的prototype,key对应方法名,
// descriptor可以理解为一些设置,比如不可修改值之类的功能
function getNameDecorator(target: any, key: string,descriptor:PropertyDescriptor) {
    console.log(target);
    console.log(key);
}
class Test {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    @getNameDecorator
    getName() {
        return this.name
    }
}
{ getName: [Function (anonymous)] }
getName
不是很懂。。。。
访问器的装饰器
其实也是一个样
// 普通方法:target对应类的prototype,key对应方法名,
// descriptor可以理解为一些设置,比如不可修改值之类的功能
function visitDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
    console.log(target);
    console.log(key);
}
class Test {
    private _name: string;
    constructor(name: string) {
        this._name = name;
    }
    get name() {
        return this._name
    }
    @visitDecorator
    set name(name: string) {
        this._name = name;
    }
}
{}
name
这个descriptor很神奇,有很多东西,具体可以看官网
属性的构造器
属性没有descriptor,要这样写
function visitDecorator(target: any, key: string) {
    const descriptor:PropertyDescriptor = {
        writable:false
    }
    return descriptor
}
参数的构造器
function paramDecorator(target: any, method: string, paramIndex: number) {
    console.log(target);
    console.log(method);
    console.log(paramIndex);
}
class Test {
    getInfo(@paramDecorator name: string, age: number) {
        // console.log(name, age);
    }
}
const test = new Test();
test.getInfo('Dell', 30)
实际应用
比如做一个通用的捕捉异常注解
const userInfo: any = undefined
function catchError(target: any, key: string, descriptor: PropertyDescriptor) {
    // 这里就代表函数里面的所有内容,比如为 reruen userInfo.name
    const fn = descriptor.value;
    descriptor.value = function () {
        try {
            fn();
        } catch (e) {
            console.log('userInfo有问题');
        }
    }
}
class Test {
    @catchError
    getName() {
        return userInfo.name
    }
}
const test = new Test()
test.getName()
userInfo有问题
常见的一些操作
1. 配置统一参数
比如一些vueuse的,都是统一一个options参数,然后要配置的话就写参数进去,无的话就默认配置。js我不知道怎么实现,但ts很容易配置
//这是一个接口,2个参数都是可选的
interface config {
  loading?: boolean
  b?: string
}
//这里,config={}是为了占位符,一般都是在最后面才做的这个
export function test(config: config = {}) {
	//定义常量
  const {
    //如果loading原本有值的话,就取config.loading里面的,否则就默认是true。这种写法对js来说是无的
    loading = true,
    b = '123',
  } = config
  console.log(loading, b)
}



















