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)
}
重写类型(interface)
比如在vue router中,
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [{
path: '/about',
name: 'about',
component: () => import('@/views/AboutView.vue'),
meta:{
title:'主页'
}
},]
})
其中的routes类型为 RouteRecordRaw[]
,
但是其中的meta类型,是RouteMeta
export declare interface RouteMeta extends Record<string | number | symbol, unknown> {
}
可以说这是个泛型,但是我们在项目中,meta不可能是多变化的嘛,最好就是统一meta的字段,方便我们以后使用,上去官网查,发现这样
这样确实可以实现我们的目标了,明确地定义meta里面是什么样子
//冲定义
declare module 'vue-router' {
interface RouteMeta {
title?: string //导航条标题
showNav?: boolean //是否显示导航条
rightText?: string //导航条
rightFunction?: () => void //点击右边文字按钮实现的方法
closeWevView?: boolean //当前页面返回是否关闭H5页面
rightIcon?: string //右上角icon
documentTitle?: string //浏览器标题
}
}
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'home',
component: HomeView,
//这样meta就统一了
meta: {
title: '主页',
showNav: true, //是否显示左上角返回按键
rightText: '按钮', //右上角按钮文字,如果没有则不显示
closeWevView: true, //当前页面点返回是否关闭H5页面
//点击右上角按钮文字触发的方法
rightFunction: () => {
console.log('ssss')
},
rightIcon: 'chat-o',
},
},
{
path: '/about',
name: 'about',
component: () => import('@/views/AboutView.vue'),
},
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: routes,
})
断言
就是比如uni.request,在函数写着返回必然是一个string类型,但是我想写成必然是number类型,可以用断言进行强制转换
const numberData = stringData as number