typescrip学习笔记2

typescrip学习笔记

准备

需要安装的依赖
npm install -g typescript

// 查看安装成功
tsc -v

npm install -g ts-node
需要的插件

Code Runner

生成配置文件
tsc --init

ts中的数据类型

变量的声明的几种类型
// 1. 声明变量并赋值
let username: string = 'ywj';
// 2. 声明变量, 无初始值, 会设置为 undefined, 赋值前不能使用, 如log
let username1: string;
// 3. 有初始值, 不设置类型, 可以是任意类型
let username2 = '12345';
// 4. 没设置初始值, 没有类型, 类型可以是任意类型, 默认初始值 undefined
let username3;
数字类型
// 02 ts的数据类型
// 1. 数字类型 number 可以是二进制, 8, 10, 16进制
let bin: number = 0b1011
let octa: number = 0o11
let ten: number = 8
let hex: number = 0x11
字符串类型
// 2. 字符串类型
let userStr: string = '这是一个str'
let resStr: string = `这是${userStr}`
布尔类型
// 3. 布尔类型  true/false
let flag: boolean = true
let flag1: boolean = false
数组类型
// 03 数组类型
let arr: string[] = ['呵呵', '嘻嘻', '哈哈']
let arr2: Array<string> = ['呵呵', '嘻嘻', '哈哈']
元组
// 04 元组 : 数组里面规定元素的类型和位置
let yuan: [string, number, boolean]
yuan = ['呵呵', 16, true]
枚举
// 05 枚举(enum) 一般大写
enum Color { Red = 11, Green = 23, Aqua = 45 }
// enum Color { Red, Green, Aqua }
let color: Color = Color.Green
// console.log(color)  // 这里输出为1, 设置值之后 23 这里的数字有些讲究
// 如果有人拿这里做文章, 建议直接掀桌子
void
// 06 void类型. 用于标识方法返回值的类型, 标识该方法没有返回值
function say(): string {
    return ''
}
function say1(): void {
    return
}

// 实际上viod函数也可以有返回值, 并且不会报错
null类型
// 07 null类型
let nobj: null = null
// console.log(typeof nobj); // 这里是 object
undefined
// 08 undefined 是没有赋值的变量
// typeof 一个没有赋值的变量 就会返回 undefined
// null 和 undefined 可以赋值给其他任意类型  严格的空校验下不行. 能不用尽可能不用, 没必要
any类型
// 09 any类型 表示任意类型
let anyType: any = 123
anyType = 'hehehe'
anyType = true
anyType.say() // 无中生有也行
let anyArr: any[] = [123, 'xixi', false]

复杂数据类型

联合类型
// 联合类型  使用 | 隔开
let lname: number | string
lname = 123
lname = 'ywj'
// lname = true    // 报错
let larr: number | number[]
larr = 123
larr = [1, 2, 3]
let larr1: number[] | string[]
larr1 = [1, 2, 3]
larr1 = ['1', '2', '3']
// 作为函数的参数
function lfn(sum: number | number[]): void {
    // do something
}
接口
// 接口
interface Person {
    name: string,
    age: number,
    say: () => string,
    show(): void
}

let p1: Person = {
    name: 'ywj',
    age: 18,
    say: () => {
        return 'ywj is handsome!!!'
    },
    show() {
        console.log('xixi');
        return ';h'
    }
}

 // Student 里面需要有Person里面的所有属性
class Student implements Person {
    name: string
    age: number
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
    say() {
        return 'hehe'
    }
    show() {
        // 这里为啥可以返回?
        return '123'
    }
}
接口继承
// 接口的继承
interface Person1 {
    name: string,
    age: number,
}

interface Musicia extends Person1 {
    use: string
}

let p2: Musicia = {
    name: 'ywj',
    age: 18,
    use: 'gita'
}

class Student1 implements Musicia {
    name: string
    age: number
    use: string
    constructor(name: string, age: number, use: string) {
        this.name = name
        this.age = age
        this.use = use
    }
}

// let p3: Musicia = {} // 这个会直接报错
// let p3 = {} as Musicia // 这个同下, 不会报错
let p3 = <Musicia>{}
p3.age = 19
p3.name = 'ywj'
p3.use = 'piano'
console.log(p3);


ts中的类
  1. ts中的class包括: 属性, 构造函数, 方法

    class Person2_copy {
        static sex: string = 'sex'  // 添加static属性之后, 就是一个静态属性, 不属于这个对象, 调用的时候直接用类名
        user: string    // 
        age: number
        constructor(user: string, age: number) {
            this.user = user
            this.age = age
        }
        say(): string {
            return '123'
        }
    }
    
    
  2. 简单的类, 属性直接赋值, 可以不用构造函数

    class Person2 {
        // 直接这样写就不用构造函数了
        user: string = 'ywj'
        age: number = 18
    }
    
  3. 属性和方法用static方法修饰的, 称为静态方法不属于new出来的对象,不能使用obj.属性来访问, 主持能通过类名来访问

    let p4 = new Person2_copy('ywj', 18)
    console.log(p4.sex)  // 这个报错
    console.log(Person2_copy.sex);
    
  4. ts类中的修饰符, public, private, protected

    // public(默认): 可以在任意地方访问
    // protected: 受保护, 可以被自身及其子类访问, 不能在被new出来的对象中访问
    // private: 私有, 自能在自定义的类中访问, 不能在被new出来的对象中访问
    
  5. 类本身就是一种类型

    class Person {
        name: string
        constructor(name:string) {
            this.name = name
        }
    }
    
    let p1:Person = new Person('ywj')
    
  6. 小tips, 如果constructor中的变量使用了public修饰, 在方法中可以直接使用.变量名访问

    class Person {
        constructor(public name:string) {}
    }
    
    // 上面相当于
    class Person {
        name: string
        constructor(name:string) {
            this.name = name
        }
    }
    
类的继承
  1. 使用extend继承

    class A {
        user: string
        private age: number
        constructor(user: string, age: number) {
            this.user = user
            this.age = age
        }
        show(): string {
            return this.user
        }
    }
    
    class B extends A {
        hobby: string
        constructor(hobby: string, user: string, age: number) {
            super(user, age)
            this.hobby = hobby
        }
    }
    
    
  2. 子类继承父类属性需要使用super(), 并传参

    class B extends A {
        hobby: string
        constructor(hobby: string, user: string, age: number) {
            super(user, age)
            this.hobby = hobby
        }
    }
    
  3. 父类中使用private修饰的属性, 子类访问不了

    const b1 = new B('千代', 'ywj', 18)
    console.log(b1.age);    // 报错
    
泛型
  1. 作用:允许在函数, 类, 接口上面, 使用占位符来表示类型, 而不是具体的类型 主要目的: 处理不特定类型的数据

  2. 泛型就相当于一个代表类型的参数, 使用的时候需要输入具体类型

  3. 函数中使用

    // T表示类型的占位符, a, 和b 都是 T类型的数据
    function fn1<T>(a: T, b: T): T[] {
        return [a, b]
    }
    
    let a1: number[] = fn1<number>(1, 2)
    console.log(a1);
    let a2: string[] = fn1<string>('hehe', 'xixi')
    console.log(a2);
    // 上面的T是一个类型的占位符
    // 使用的时候, 需要指定T的具体类型
    
  4. 接口中使用

    // 在接口中使用
    interface P2<T, K> {
        name: T,
        age: K
    }
    let pp2: P2<string, number> = {
        name: 'ywj',
        age: 18
    }
    
  5. 类中使用

    class P3<T, K> {
        name: T
        age: K
        constructor(name: T, age: K) {
            this.name = name
            this.age = age
        }
        getInfo(): T {
            return this.name
        }
    }
    let pp3: P3<string, number> = new P3<string, number>('ywj', 18)
    
泛型约束

​ 控制泛型的类型范围

​ 用法

// 这里的T只能是string 或 number
// T extends string 这个表示只能是 string
function fn1_copy<T extends string | number>(a: T, b: T): T[] {
    return [a, b]
}
泛型与接口联合使用
interface Msg {
    name: string,
    age: number
}

let p8: Msg = {
    name: 'ywj',
    age: 18
}
// 这里的T是Msg的健 name 或 age中的其中一个
function getmsg<T extends keyof Msg>(msg: Msg, key: T): Msg[T] {
    return msg[key]
}

let res = getmsg(p8, 'age')
console.log(res);

装饰器

​ 作用: 不改变原代码的前提下 实现在原有逻辑代码的前后增加功能

类装饰器(ClassDecorator)

​ 用法: 给class上面加上注解

​ 例如: 给类添加一个属性和方法

​ 注意后面使用的时候, 需要使用断言as any

​ 下面这个是没有传参的情况

// 这里面的fn是Ss的构造函数
const app: ClassDecorator = (fn): void => {
    // console.log(fn, '111');
    fn.prototype.age = 18
    fn.prototype.say = () => {
        console.log('一直18岁');
    }
}
// 这玩意就是注解 @app
@app
class Ss {
    name: string
    constructor(name: string) {
        this.name = name
    }
}

let s1: Ss = new Ss('ywj')
// console.log(s1.constructor);
// console.log(s1.age);    // 直接访问age报错

// 这里要用断言(s1 as any)
console.log((s1 as any).age);
(s1 as any).say()

​ 需要传参的情况

const app = (address: string): ClassDecorator => {
    return (fn): void => {
        // console.log(fn, '111');
        fn.prototype.age = 18
        fn.prototype.address = address
        fn.prototype.say = () => {
            console.log('一直18岁');
        }
    }
}

@app('北京以北')
class Ss {
    name: string
    constructor(name: string) {
        this.name = name
    }
}

let s1: Ss = new Ss('ywj')
// 这里要用断言(s1 as any)
console.log((s1 as any).age);
console.log((s1 as any).address);
方法装饰器(MethodDecorator)

​ 用法: 给方法上面加上注解

​ 在new对象的时候执行

​ 需要注意的是:

  1. 使用方法是在方法的上一行加上@get
  2. 方法3个参数, 没有返回值
    1. target表示对象本身, 能通过target访问方法,调用方法(通过断言) 不能访问属性
    2. propertyKey表示方法名称
    3. descriptor表示方法的解构, 可以通过descriptor.value()调用方法, 也可以传参
  3. class本身也能作为一种类型
const get: MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void => {
    console.log(1, target);     // 目标对象
    console.log(2, propertyKey);    // 方法名
    console.log(3, descriptor); // 方法的结构

    // console.log(4, (target as Demo1).user); // undefined 获取不到属性
    // (target as Demo1).getData('www.hehe.com')    // 可以通过target来调用

    descriptor.value('12345')  // 可以通过这个调用方法, 也能传参
    console.log('上山打老虎');


}

class Demo1 {
    user: string
    constructor(user: string) {
        this.user = user
    }
    // 这个是在对象生成的时候执行
    @get
    getData(url: string) {
        console.log(url);

    }
}

let d1: Demo1 = new Demo1('ywj')
d1.getData('颗粒大魔王')

​ 传参的情况

​ 注意写法

const get = (url: string): MethodDecorator => {
    return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void => {
        console.log(url, 'url');
        descriptor.value(url)  // 可以通过这个调用方法, 也能传参
        console.log('上山打老虎');
    }
}
class Demo1 {
    user: string
    constructor(user: string) {
        this.user = user
    }
    // 这个是在对象生成的时候执行
    @get('www.ywj is handsome .com')
    getData(url: string) {
        console.log(url);

    }
}
ts模块

​ 定义模块 math.ts

​ 导出使用 export

export function add(a: number, b: number): number {
    return a + b
}
export function delt(a: number, b: number): number {
    return a - b
}

​ 使用模块

​ 导入使用 import {} from 模块

​ 可以有两种方法

​ 方法1

import { add, delt } from "./math";

console.log(add(1, 2));

​ 方法2

import * as math from './math'

console.log(math.add(2, 3));
console.log(math.delt(2, 3));

​ 引用时起别名

import {addition as add} from 'xx'
add(1,2)

​ 如果导出的模块中有export default, 导入的时候就不用解构了, 直接

import 模块名 from 'XX'
// 模块名 可以随便写, 但别太随便
小练习

​ 目标: 模拟后台获取一些数据, 显示在页面

​ 准备: 一个data.json文件, 一个index.ts文件, 一个index.html文件

​ 注意, index.html中不能直接引入index.ts, 需要将index.ts编译成index.js

​ 命令 -- 注意要跳转到目标文件夹下

tsc index.ts

​ 需要注意的是

  1. fetch是浏览器自带的, 返回一个promise, 封装的时候, 没有返回值可需要给个Promise
  2. 分析数据结构, 先从data里面对象数组的结构开始, 一步一步向外面定义数据类型, 可以使用泛型, 会方便
  3. 获取到的数据需要.json一下
  4. div也是有type的, HTMLDivElement
  5. 最后编译的时候报错了, 但是编译成功了

​ data.json

{
    "code": 200,
    "data": [
        {
            "user": "ywj1",
            "age": 18
        },
        {
            "user": "littleship",
            "age": 16
        }
    ],
    "msg": "ok"
}

​ index.ts

interface DateType {
    user: string
    age: number
}

interface ResType<T> {
    code: number,
    data: T[],
    msg: string
}

// fetch('./data.json')
//     .then((res: Response) => res.json())
//     .then((res: ResType<DateType>) => {
//         console.log(res.data[0]);
//         let app: HTMLDivElement = document.querySelector("#app") as HTMLDivElement
//         res.data.forEach((item: DateType) => {
//             let div1: HTMLDivElement = document.createElement('div') as HTMLDivElement
//             div1.innerHTML = `<span style="margin-right: 20px">姓名: ${item.user}</span><span>年龄: ${item.age}</span>`
//             app.append(div1)
//         })
//     })

async function getList(): Promise<void> {
    let response: Response = await fetch('./data.json')
    let res: ResType<DateType> = await response.json()
    let app: HTMLDivElement = document.querySelector("#app") as HTMLDivElement
    res.data.forEach((item: DateType) => {
        let div1: HTMLDivElement = document.createElement('div') as HTMLDivElement
        div1.innerHTML = `<span style="margin-right: 20px;color: aqua">姓名: ${item.user}</span><span>年龄: ${item.age}</span>`
        app.append(div1)
    })
}

getList()

​ index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>typescript</title>
    <script src="index.js"></script>
</head>

<body>
    <div id="app"></div>
</body>

</html>

感谢

​ 特别感谢Ju加油坊老哥

posted @   littlelittleship  阅读(7)  评论(1编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
历史上的今天:
2022-06-27 10. watch的实现原理
2022-06-27 9. 计算属性的实现原理
2022-06-27 8. 数组更新的实现原理
2022-06-27 7. mixin的实现原理
点击右上角即可分享
微信分享提示