学习ts基础 笔记大全

1.const regexp:RegExp = /^1/  正则类型

2.const date:Date = new Date()  日期类型

3.const error:Error = new Error()

new 出来的返回的都是对象所以前面必须是大写 

let b:Boolean = new Boolean(1)

unknown和any区别

1.unknown比any更安全

2.unknwon类型不能去调用属性和方法不能点出来东西

3.unknwon只能充当父类型使用 不能赋值给别的类型 他只能赋值给自身或any类型

Object 属于原型链顶端所以包含所有类型可以赋值所有类型的值

object不可以赋值原始类型其他引用类型都可以赋值 数组 对象 函数都可以

{}也是包含所有类型但是无法对变量进行任何赋值操作 少用

interface接口 一般用于定义对象类型

如果遇到重名的内部属性会自动重合 属性类型不能多也不能少

使用索引签名方法 定义任意key 就是前面的会校验规则后面的值不在校验

interface Axxx {
    name: string
    age:number
    readonly cb:() =>boolean
    [propName:string]:any //值的类型定义什么那么后面就得是什么类型
}

let a:Axxx = {
    name:'小猫',
    age: 18,
    a:1,
    b:2
}

//interface定义函数类型
interface Fn {
    (name:string):number[]
}
const fn:Fn = function (name:string) {
    return [1]
}

1.?可选 2.不允许在外面修改的话使用修饰符readonly使他变为只读属性 一般多用于函数

3. interface接口继承extends 继承后属性相加在一块

 定义数组类型

number[] or Array<number> 两种方法都可以

// 定义对象数组使用
interface X {
    name: string
}
const arr:X[] = [{name:'qwes'}]

//定义多维数组
let arr:number[][] = [[1]]
or
let arr:Array<Array<number>>

// 如果数组中什么类型都有 用any或者元组类型就是一个一个的定义类型
let arr:any[] = [1,'qwe',{}]

// 剩余参数可以是具体类型或者任何类型的数组
function a(...args:any[]) {
    let a:IArguments = arguments
}
// arguments内部类型
interface A {
    callee: Function
    length:number
    [index:number]:any
}

函数类型

参数写几个就得传几个 除非给他默认值 或者 加?可选运算符 如 num?:number

// interface定义参数
interface User {
    name:string
    age:number
}

const fn = function(user:User):User {
    return user
}
let a = fn({name:'',age:18})

函数重载 重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。如果参数类型不同,则操作函数参数类型应设置为any。参数数量不同你可以将不同的参数设置为可选。

// 重载函数 两套规则
function fn(params:number):void
function fn(params:number,params2:string):void
// 用于执行逻辑的
function fn(params:any,params2?:string):any {
    return params + params2
}

联合类型

  

let phone:number | string = 

let fn = function(type:number | boolean):boolean {
    return !!type
}

交叉类型

interface People {
    name:string
    age:number
}
interface Man {
    sex:number
}
// 两个接口的类型都需要添加
const qwe = (man:People & Man):void {
    console.log(man)
}

类型断言

let fn = function (num:number | string):void {
    console.log((num as string).length)
}
fn(123456)
//
interface A {
    run:string
}

interface B{
    build:string
}
// 就想在形参上点出run这个时候将形参就断言为类型A 但是值为undefined
let fn = function (type:A | B):void {
    console.log((tyoe as A).run)
}
fn({build:'123'})

// 可以在window上使用
(window as any).abc = 123

//欺骗ts
const fn = (type:any):boolean=> {
    return type as boolean
}
let bbb = fn(1)

class类

class类的修饰符

public内部外部都能访问

private 私有变量只能在内部访问

protected 内部和子类中访问

// ts中声明变量需要在前面提前声明一遍 如果某个变量没有使用ts报红的话需要给个默认值或者赋个值
class Person {
    public name:string
    private age:number
    protected sub:boolean = false
    // 静态变量
    static aaa:string = '1232131'
    // 构造器中也不能通过this访问静态变量或方法可以通过class直接调用Person.run()    constructor (name:string,age:number,sub:boolean) {
        this.name = name
        this.age = age
        this.sub = sub
    }
    // 静态方法 静态方法中不能使用this的变量只能使用static定义的变量
    static run() {
        reutrn '789'
    }
}
// 在子类中也不能访问到private定义的变量 但是public和protected可以访问
class Man extends Person {
    constructor () {
        super('tang', 22 ,false)
    }
}
// 静态属性可以通过类直接调用
Person.aaa
Person.run()
// 创建实例
let p = new Person('小满',22,false)

通过接口约束class类函数

interface Person {
    run(type:boolean):boolean
}

interface H {
    set():void
}

class A {
    params:string
    constrctor(params) {
        this.params = params
    }
}

// 多个类型用,链接
class Man extends A implements Person,H {
    run (type:boolean):boolean {
        return type
    }
}

class抽象类

应用场景如果你写的类实例化之后毫无用处此时我可以把它定义为抽象类 或者 你也可以把它作为一个基类:通过创建一个派生类继承抽象类去实现它的一些方法,这个抽象类也能叫基类

// 抽象类 无法创建实例
abstract class A {
    name:string
    constructor(name:string) {
        this.name = name
    }
     // 如果不用abstract定义函数B类继承后还是可以正常使用的
    // 加了抽象修饰符就无法在函数中写逻辑了
    abstract getName(): string
}
// 派生类
class B extends A {
    constructor() {
        super('qwe')
    }
    // 按照抽象类定义
    getName():string {
        return this.name
    }
}

元组类型

元组是固定数量不同类型的元素的组合


// 元组类型 加上readonly为只读不可以更改
const arr: readonly [number, boolean] = [1, false]

arr[0] = 555 //错误
arr.push(1) //错误

//加上名称可以设为可选
const arr: readonly [x:number,y?:string] = [1,'qwe']

//type 类型别名
type first = typeof arr[0]

枚举类型 

数字枚举、字符串枚举、异构枚举

const枚举编译成js时会直接将枚举编译为值而普通枚举会编译为对象

// 默认值为0,1,2 如果给第一个赋值1后面会累加 如过要给其中一个赋值字符串那么就要全部赋值
enum Color {
    red
    green
    blue
}
// 调用
Color.red

// 接口枚举
interface A {
    red:Color.red
}
let obj:A = {
    red:Color.red
} 

// const 枚举
const enum Types {
    success,
    fail
}

let code:number = 0
if(code === Types.success) {}

// 反向映射 数字类型可以映射 字符串不可以
enum Types {
    success = 456
}
let success:number = Types.success
// 打印出来他对应的key
console.log(Types[success])

类型推论 

声明了一个变量但是没有定义类型 ts会在没有明确的指定类型的时候推测出一个类型,这就是类型推论

类型别名

type可以定义任何类型

type和interface区别

1. interface可以通过extends继承

2.type可以写联合类型 interface必须在内部定义属性后才能定义

3. interface可以重名合并 type不可以

// extends 在type中是包含的意思 左边的值会作为右边类型的子类型
type num = 1 extends number ? 1 : 0 //返回1

  类型层级

1.any unknow

2.Object

3.Number

4.number string

5.never

never 

表示不应该存在的状态

type aaa = string | number //这个时候aaa就是never 不存在这种情况

// 应用场景
//不可能有返回值 只抛出异常
function error(message:string):never {
    throw new Error(message)
}
// 死循环也可以使用
function loop():never {
    while(true) {
    
    }
}

//如果后面的人增加了一个接口但是函数中没有添加逻辑这个时候default兜底逻辑就会报错提醒 因为never类型无法被赋值

interface A {
    type:'保安'
}

interface B {
    type:'小说'
}
interface C {
    type:'摸鱼'
}
type All = A | B | C
function type(val:All) {
    switch(val.type) {
        case '保安':
            break
        case '小说':
            break
        case '保安':
            break
        default:
            const check:never = val;
    }
}

Symbol

es6新增类型 通过Symbol构造函数创建的 ,可以传递参数为唯一标识,只支持string和number类型的参数。

一般用再对象属性类名当键名比较多

let s:symbol = Symbol('二蛋')
let num:symbol = Symbol('二蛋')

console.log(s === num) //不等于 因为内存地址指针位置不同所以是唯一值

let obj = {
    [num]: 'value',
    [s]: '12',
    name: 'tang',
    age: 18
}

// 这些方法都无法循环到symbol属性的键名
for(const k in obj) {
    console.log(k)
}

console.log(Object.keys(obj))

console.log(Object.getOwnPropertyNames(obj))

console.log(JSON.stringify(obj))

// 以下方法可以循环到
// 可以取到对象里symbol类型的键名 但取不到普通类型的
console.log(Object.getOwnPropertySymbols(obj))
// 普通类型和symbol类型都可以取到
console.log(Reflect.ownKeys(obj))

 Symbol.iterator迭代器和生成器for of

数组或者伪数组都有这个属性但是{}对象是没有的

// 通过迭代器方式获取值 当到最后一个没有值时dong为true
let arr:Array<number> = [4,5,6]

let it:Iterator<number> = arr[Symbol.iterator]()

console.log(it.next()) // {value: 4, done:false}
console.log(it.next())// {value: 5, done:false}
console.log(it.next())// {value: 6, done:false}
console.log(it.next())// {undefined, done:true}

// 封装一个小的迭代器函数 迭代器原理
type mapKeys = string | number
let set:Set = new Set([1,2,3])

let map:Map<mapKeys, mapKeys> = new Map()
map.set({1,'wang'})
map.set({2,'yang'})

function gen(erg:any) {
    let it:Iterator<any> = erg[Symbol.iterator]{}
    let next:any = {done:false}
    while(!next.done) {
        next = it.next()
        if(!next.done) {
            console.log(next)
        }
    }
}
gen()

for of就是js用迭代器实现的语法糖直接返回值但是也不支持{}对象 

ts泛型 

函数泛型:语法为函数名字后面跟一个<参数名>参数名可以随便写 例如写一个T当我们使用这个函数的时候把参数的类型传进去就可以了

function add<T>(a:T,b:T):Array<T> {
    return [a,b]
}

add<number>(1,2)

function sub<T | U>(a:T,b:U):Array<T | U> {
    reutrn [a,b]
}

sub<number, string>(1,'a')

// 泛型约束
interface Len {
    length:number
}
function getLength<T extends Len>(val:T) {
    return val.length
}

使用keyof约束对象

其中使用了TS泛型和泛型约束。首先定义了T类型并使用extends关键字继承object类型的子类型然后使用keyof操作符获取T类型的所有键,它的返回类型是联合类型,最后利用extends关键字约束K类型必须为keyof T联合类型的子类型

// 约束key
function prop<T,K extends keyof T>(obj:T,key: K) {
    return obj[key]
}

let o = {a:1,b:2,c:3}

prop(o, 'a')

//类中用泛型
class Sub<T>{
    attr:T[] = []
    add(a: T): T[] {
        return [a]
    }
}
let s = new Sub<number>()
s.attr([1,2,3])
s.add(3)

type interface中使用泛型

// type
type A<T> = number | string | T

let a:A<boolean> = false

// inteface

interface Data {
    mas:string
}

let obj:Data = {
    mas:'qwe'
}

泛型可以一次定义多个也可以给默认值

function add<T = number,K = string>(a:T,b:K):Array<T | K> {
    return [a,b]
}

 tsconfig.json 配置文件

常用

1.include
指定编译文件默认是编译当前目录下所有的ts文件

2.exclude
指定排除的文件

3.target
指定编译js 的版本例如es5  es6

4.allowJS
是否允许编译js文件

5.removeComments
是否在编译过程中删除文件中的注释

6.rootDir
编译文件的目录

7.outDir
输出的目录

8.sourceMap
代码源文件

9.strict
严格模式

10.module
默认common.js  可选es6模式 amd  umd 等

namespace命名空间 

ts和ECMA2015一样,任何包含顶级import或export的文件都被当成一个模块,相反的,如果一个文件不带有顶级的import或export声明,那么它的内容被视为全局可见的

命名空间通过export将想要暴露的部分导出,如果不用export导出是无法读取其值的

// 正常使用
namespace A {
    export const a = 1
}
console.log(A.a)

// 嵌套命名空间的使用
namespace A {
    export namespace C {
         export const c = 5   
    }
}
console.log(A.C.c)

// 简化命名空间
import AAA = A.C
console.log(AAA.c)

// 抽离命名空间就是导入一个命名空间然后使用

// 命名空间如果重名就会合并

三斜线指令 

三斜线指令是包含单个XML标签的单行注释。注释的内容会做为编译器指令使用
三斜线指令仅可放在包含它的文件的最顶端。一个三斜线指令的前面只能出现单行或多行注释,这包括其它的三斜线指令。如果它们出现在一个语句或声明之后,那么它们会被当做普通的单行注释,并且不具有特殊的涵义。
///<reference path="...”/>指令是三斜线指令中最常见的一种。它用于声明文件间的 依赖.

三斜线引用告诉编译器在编译过程中要引入的额外的文件
你也可以把它理解能import,它可以告诉编译器在编译过程中要引入的额外的文件

/// <reference path="index2.ts" /> //使用方法和import一样引入后可以直接使用

/// <reference types="node" /> //可以引入声明文件

声明文件d.ts

declare当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能

有两种方法 一种是通过 npm i --save-dev @types/express(这块是你需要声明的插件)

另一种是创建.d.ts自己声明

import express from 'express'

const app = express()
const router = express.Router()
app.use('/api', router)

router.get('/api', (req: any, res: any) => {
  res.json({
    code: 200
  })
})

app.listen(9001, () => {
  console.log('9001')
})

// 声明文件
declare module 'express' {
  interface Express {
    (): App
    Router(): Router
  }
  interface Router {
    get(path: string, cb: (req: any, res: any) => void)
  }
  interface App {
    use(paht: string, router: any): void
    listen(port: number, cb?: () => void)
  }
  const express: Express
  export default express
}

Mixins

ts混入Mixins其实vue也有 可以把它看作合并

1.对象混入

可以使用es6的Object assign合并多个对象

interface Name {
    Name: string
}
interface Age {
    age: number
}
interface Sex {
    sex: string 
}

let name:Name = {name: 'qwe'}
let age:Age = {age:18}
let sex:Sex = {sex:1}

Object.assign(name,age,sex)

2.类混入

class A {
  type!: boolean
  changeType(): void {
    this.type = !this.type
  }
}

class B {
  name!: string
  getName(): string {
    return this.name
  }
}

class C implements A, B {
  type: boolean = false
  name: string = 'qwe'
  changeType!: () => void
  getName!: () => string
}

mixins(C, [A, B])
function mixins(curCls: any, itemCls: any[]) {
  itemCls.forEach(item => {
    Object.getOwnPropertyNames(item.prototype).forEach(name => {
      curCls.prototype[name] = item.prototype[name]
    })
  })
}

let qwe = new C()
console.log(qwe.getName())

Decorator 装饰器是一项实验性特性,在未来的版本中可能会发生改变

它们不仅增加了代码的可读性,清晰地表达了意图,而且提供一种方便的手段,增加或修改类的功能

若要启用实验性的装饰器特性,你必须在命令行或tsconfig.json里启用编译器选项

 

装饰器是一种特殊类型的声明,它能够被附加到类声明方法, 访问符属性参数上。

//定义一个类装饰器函数 他会把ClassA的构造函数传入你的watcher函数当做第一个参数
const watcher: ClassDecorator = (target: Function) => {
    target.prototype.getParams = <T>(params: T):T => {
        return params
    }
}

//使用的时候 直接通过@函数名使用
@watcher
class A {
    constructor() {
 
    }
}


const a = new A();
console.log((a as any).getParams('123'))

装饰器工厂

其实也就是一个高阶函数 外层的函数接受值 里层的函数最终接受类的构造函数

const watcher = (name: string): ClassDecorator => {
    return (target: Function) => {
        target.prototype.getParams = <T>(params: T): T => {
            return params
        }
        target.prototype.getOptions = (): string => {
            return name
        }
    }
}
 
@watcher('name')
class A {
    constructor() {
 
    }
}
 
const a = new A();
console.log((a as any).getParams('123'));

装饰器组合

就是可以使用多个装饰器


const watcher = (name: string): ClassDecorator => {
    return (target: Function) => {
        target.prototype.getParams = <T>(params: T): T => {
            return params
        }
        target.prototype.getOptions = (): string => {
            return name
        }
    }
}
const watcher2 = (name: string): ClassDecorator => {
    return (target: Function) => {
        target.prototype.getNames = ():string => {
            return name
        }
    }
}
 
@watcher2('name2')
@watcher('name')
class A {
    constructor() {
 
    }
}
 
 
const a = new A();
console.log((a as any).getOptions());
console.log((a as any).getNames());

方法装饰器

返回三个参数

对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。

成员的名字。

成员的属性描述符

const met:MethodDecorator = (...args) => {
    console.log(args);
}
 
class A {
    constructor() {
 
    }
    @met
    getName ():string {
        return '小满'
    }
}
 
 
const a = new A();

属性装饰器

返回两个参数

对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。

属性的名字。

const met:PropertyDecorator = (...args) => {
    console.log(args);
}
 
class A {
    @met
    name:string
    constructor() {
 
    }
   
}
 
 
const a = new A();

参数装饰器

返回三个参数

对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。

成员的名字。

[ {}, 'setParasm', 0]

const met:ParameterDecorator = (...args) => {
    console.log(args);
}
 
class A {
    constructor() {
 
    }
    setParasm (@met name:string = '213') {
 
    }
}
 
 
const a = new A();

### 关于 TypeScript学习资源 TypeScript 是一种由微软开发的开源编程语言,它是 JavaScript 的超集,增加了静态类型定义等功能。以下是关于 TypeScript 学习的一些推荐内容: #### 尚硅谷 TypeScript 学习笔记 PDF 或教程 尚硅谷提供了丰富的技术课程和学习资料,其中包括针对 TypeScript 的教学视频和文档。可以通过以下方式获取相关资源: - 访问尚硅谷官网或者其官方授权的学习平台,查找与 TypeScript 相关的内容。 - 下载对应的 PDF 文档或观看在线视频教程。 #### TypeScript 基础概念 TypeScript 提供了许多增强功能来改进代码质量和可维护性[^1]。例如,在 Vue 中使用 `v-model` 时可以结合 TypeScript 来实现更严格的类型检查。通过引入自定义 Hooks 文件(如 `useXxx.js`),开发者能够更好地管理状态逻辑并利用 TypeScript 定义接口和类型[^2]。 另外,在现代前端框架中,Pinia 是 Vue 3 推荐的状态管理库之一。它支持 TypeScript 开箱即用的功能,并允许我们轻松创建存储模块以及操作其中的数据结构[^5]。 #### 数据绑定与响应式机制 当我们在模板里访问变量时无需显式调用 `.value` 属性即可完成渲染工作[^4]。这是因为内部采用了 Proxy 对象作为核心工具实现了高效的拦截器模式[^3]。这种设计使得整个应用变得更加简洁高效同时也更容易理解和调试。 ```typescript // 示例:简单的 TypeScript 类型声明 class User { name: string; age?: number; constructor(name: string){ this.name = name; } } const userInstance = new User('Alice'); console.log(userInstance); ``` #### 路由配置实例 对于单页面应用程序来说,合理设置路由是非常重要的一步。下面展示了一个基本重定向路径的例子: ```javascript { path:'/', redirect:'/about' } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值