typescript学习笔记(小满zs+官方文档)

ts官方文档

小满主页

1

安装ts

npm i typescript -g

tsc -v 查看版本号

调试

tsc --init 初始化ts,生成tsconfig.json

tsc -w 编译出一个js文件、

node index.js node调试js文件

其他

NaN、Infinity也算number类型
还有一些进制也算 比如hex

void类型是null/undefined,一般用于函数
严格模式void不能被赋为null

严格模式在cfg里面"strict"里改
非严格模式下,undefined和null可以穿插赋值

2

安装库

npm i ts-node -g

配置镜像库:
npm i xmzs -g
其他命令
mmp ls
mmp -h
mmp use

生成package.json
npm init -y

生成配置文件node_modules
npm i @types/node -D

然后就可以直接使用 ts-node index.ts来看到输出了

类型

顺序
  1. any unknown
  2. Object
  3. Number String Boolean
  4. number string boolean
  5. 1 “qwq” false
  6. never
其他

unknown 只能赋值给自身或者any
unknown 不能用.读到属性

3 Object、object、{}

Object

和any差不多

object

引用数据类型

{}

相当于new Object
但是赋值后无法修改

4 接口

特点

  1. 接口和类型必须一模一样
  2. 接口重名,重合
  3. 索引签名
    [propName:string]:any
    让其他属性取消强校验
  4. ?标志属性非必填
  5. readonly 限制只读,常用于函数和id
  6. 继承 extend
  7. 函数接口,写对参数和返回值的约束
    注意限制的位置
interface Fn {
  (name: string): number[];
}

const a: Fn = function fn(name: string) {
  return [1];
};

5 数组

number[] = Array
number[][] = Array>

对象数组用interface

interface x {
  name: string;
}

const arr: x[] = [{ name: "qwq" }];

6 函数

  1. 函数定义类型和返回值
    返回值在()后定义
  2. 默认值和可选参不可一起用
  3. 参数是对象,interface对参数约束就好
  4. ts可以定义this的类型
    js不能用
interface Obj {
  user: number[];
  add(this: Obj, num: number): void;
}

const obj: Obj = {
  user: [1, 2, 3],
  add(num) {
    this.user.push(num);
  },
};
obj.add(4)
console.log(obj);

  1. 函数重载
let user: number[] = [1, 2, 3];
//传number类型数组 添加
function findNum(add: number[]): number[];
//传id,单个查询
function findNum(id: number): number[];
//没有传,查全部
function findNum(): number[];
//实现
function findNum(ids?: number | number[]): number[] {
  //判断类型是否为数组用Array的方法
  if (Array.isArray(ids)) {
    user.push(...ids);
    return user;
  }
  //判断是否为number这类用typeof
  else if (typeof ids == "number") {
    return user.filter((v) => v == ids);
  }
  //最后也要有返回值
  else {
    return user;
  }
}
findNum([4]);
console.log("查全部", findNum());
console.log("查单个", findNum(1));

6

| 联合
!!强转
& 交叉(将两个类型合起来)
类型断言:
(type as A)或者(type)
注意:断言只能欺骗一下ts编译器,实际传数据传的啥类型还是啥类型

7 内置对象

第7节的代码雨还是很有意思的
https://www.bilibili.com/video/BV1wR4y1377K?p=8&vd_source=133a4c6b8765759be3947374e6336df7

ecma

Number Date RegExp Error XMLHttprequest

let num: Number = new Number(1);

dom

bom

有点多,先留个坑后面再整理

8 class

和java/c++里学的类实现差不多

教程用例比较复杂,可以理解为在手写vue源码的一部分,虚拟dom渲染为真实dom

  1. 基本用法
    extends:继承
    implements:使用implements来实现一些类共有方法属性的提取,interface提取,implements实现

  2. 修饰符
    readonly
    public
    private 只能内部
    protected 给子类和内部
    在外面都是不能用.访问到的

  3. super调父类方法
    实质为父类的prototype.constructor.call

  4. static
    静态方法只能被类本身调用,实例无法调用
    在static方法里的this也只能访问带static的东西。
    原因:
    static属性加载在其他属性之前,static初始化的时候别的属性还不存在,调用不了

  5. getter setter
    用get和set关键字
    存取器要求你将编译器设置为输出ECMAScript 5或更高。 不支持降级到ECMAScript 3。

9 class

抽象类abstract
猫狗动物的例子挺好的hh

特点:

抽象方法只能描述不能实现
抽象类不能被实例化

类可以当作接口使用
类定义会创建两个东西:类的实例类型和一个构造函数。 因为类可以创建出类型,所以你能够在允许使用接口的地方使用类。

自己写的一个很屑的案例

abstract class Animal {
  type: string;
  constructor(type: string) {
    this.type = type;
  }
  abstract speak(): void;
}

class Cat extends Animal {
  constructor(name: string) {
    super("Cat");
    this.name = name;
  }
  name: string;

  speak(): void {
    console.log(`${this.type} + ${this.name}`);
  }
}

let c = new Cat("qwq");
c.speak();

不要整出例如这样的代码就可以了

//不能实例化
let d = new Animal()
//不能实现
abstract speak(): void{
    console.log(this.type);
  }


10 元组

const arr: [x: string, y: number] = ["123", 123];

越界后会推断为联合类型

arr.push(1234) 对
arr.push(true)

可用readonly修饰(const不能让元组只读)
可用?

使用typeof获取元组的类型

type first = typeof arr[0]

略显奇怪的用法

type first = typeof arr["length"]

可以得到元组的大小为2

实例:用于描述excel数据

11 枚举

enum关键字
可用可不用,相当于是一个对象

数字枚举

enum Color {
  //默认从0开始
  red = 1,
  //为2
  blue,
  white = 6,
}

console.log(Color.blue);

字符串枚举

必须都初始化一下

异构枚举

混着写是可以的

接口枚举

不知道有什么用

enum Color {
  red = "qwq",
  blue = 1,
}

interface A {
  red: Color.red;
}

let obj: A = {
  red: Color.red,
};

const枚举

不知道有什么用

直接编译为常量

const enum Color {
  red,
  blue,
}

let code: number = 0;
if (code === Color.red) {
  console.log("yes");
}

编译为js

var code = 0;
if (code === 0 /* Color.red */) {
    console.log("yes");
}

不加const的编译:对象形式

var Color;
(function (Color) {
    Color[Color["red"] = 0] = "red";
    Color[Color["blue"] = 1] = "blue";
})(Color || (Color = {}));
var code = 0;
if (code === Color.red) {
    console.log("yes");
}

反向映射

字符串不可以用这玩意
可以互相取挺方便的,value拿key就用这招

enum Color {
  red,
  blue,
}

let code: number = Color.red;

let key = Color[code];

console.log(code);//0
console.log(key);//red

11 类型推论 类型别名

类型推论

不写:的情况下,会自动推断变量的类型,默认any

别名

type关键字

type-interface
type不能用extends,可以使用&,|来定义交叉、联合类型
type重名不会合并

高级用法

type num = 1 extends never ? 1: 0

num为0,extends:包含
左边的值会作为右边类型的子类型

12 never类型

type a = number & string

a为never类型

然后对于函数,死函数/运行报错函数设置为never类型

function a():never{
  while(true){

  }
}

never处于类型的最底级,联合没用

一般用于switch语句中default的部分,通过never类型的错误找到逻辑错误

13 symbol类型

基础

唯一标识,在不同的内存空间

let a1: symbol = Symbol(1);
let a2: symbol = Symbol(1);

console.log(a1 == a2);//false

Symbol.for
for全局symbol是否注册过这个key,有就用,无才创建。但是需要传字符串值

let a1: symbol = Symbol.for("1");
let a2: symbol = Symbol.for("1");

console.log(a1 == a2);//true

用处:解决属性的key取重复的问题
因为对symbol而言,就算里面的值是一样的,也算不同的

let a1: symbol = Symbol(1);
let a2: symbol = Symbol(1);

let obj = {
  [a1]: 123,
  [a2]: 234,
  //name: "qwq",
  //name: "sayori",
  //报错:对象文本不能具有多个名称相同的属性,在js中会下面的覆盖上面的

};

console.log(obj);
//{ [Symbol(1)]: 123, [Symbol(1)]: 234 }

问题:
for in 、Object.keys 、Object.getOwnPropertyNames都不能读到symbol
需要使用
Object.getOwnPropertySymbols,但是这个只能单独取symbol

使用Reflect.ownKeys才可以都取到

生成器 generator函数

function* gen() {
  //同步/异步都可以
  yield Promise.resolve("qwq");
  yield "123";
  yield "sayoriqwq";
}

const A = gen();
console.log(A.next());
console.log(A.next());
console.log(A.next());
console.log(A.next());

输出:

{ value: Promise { 'qwq' }, done: false }
{ value: '123', done: false }
{ value: 'sayoriqwq', done: false }
{ value: undefined, done: true }

done为true说明迭代完成了

迭代器

和生成器其实差不多,也是一个函数,用法也是一样的

let arr = [1, 2, 3];

console.log(arr[Symbol.iterator]().next().value);//1

set map
学过c++的stl应该对这玩意不陌生
set自带去重

let set: Set<number> = new Set([1, 1, 2, 2]);
console.log(set);//Set(2) { 1, 2 }

map相关方法

let map: Map<any, any> = new Map();

let arr = [1, 2, 3];
map.set(arr, "qwq");
console.log(map.get(arr));//qwq

然后讲了一些伪数组
arguments,querySelectorAll

迭代器应用场景:支持遍历所有这些乱七八糟的数据类型

语法糖 for of
二者等效,也可以用来遍历map、array等

let set: Set<number> = new Set([1, 1, 2, 3]);

const each = (value: any) => {
  let It: any = value[Symbol.iterator]();
  let next: any = { done: false };
  while (!next.done) {
    next = It.next();
    if (!next.done) {
      console.log(next.value);
    }
  }
};

for(let value of set){
  console.log(value);
}

注意:for of对象不能用,对象身上没有iterator

数组解构:底层原理也是调iterator
注意:对象解构不是用的这个

使对象支持for of:手动实现iterator方法

let obj = {
  max: 5,
  current: 0,
  //配置迭代器
  [Symbol.iterator]() {
    return {
      //迭代到下一层之前把属性速记
      max: this.max,
      current: this.current,
      next() {
        //迭代完成
        if (this.current == this.max) {
          return {
            value: undefined,
            done: true,
          };
        }
        //继续迭代 
        else {
          return {
            value: this.current++,
            done: false,
          };
        }
      },
    };
  },
};

for (let value of obj) {
  console.log(value);
}

console.log([...obj]);

14 泛型

动态类型

概念

function qwq<T>(a: T, b: T): T[] {
  return [a, b];
}
//一样的,一般让ts自己推断类型
console.log(qwq(1, 2));
console.log(qwq<number>(1, 2));

类型泛型:

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

let a: A<null> = null;

接口也可以用

相比于any,泛型可以推断类型,而any只能是any

泛型也可以支持多个

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

add(1,false)

可以自己写一下代码,就可以看到在写的时候ts对类型的推断了,不传的时候是unknown,传的时候推断为我们传的值的类型

实战

调接口的时候用
https://www.bilibili.com/video/BV1wR4y1377K/?p=17&spm_id_from=pageDriver&vd_source=133a4c6b8765759be3947374e6336df7

泛型约束

控制类型的范围

interface Len {
  length: number;
}

function fn<T extends Len>(a: T) {
  a: length;
}

fn(111);//错,number类型没有length属性
fn("1q213");
fn([1, 2, 3]);

keyof 约束对象中的key

let obj = {
  name: "sayori",
  age: 123,
};

//T限制为传引用类型,K限制为传T的key值
function fn<T extends object, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

console.log(fn(obj, "name"));//sayori
console.log(fn(obj, "qwe"));//报错,qwe不是obj里的一个key

而且在写代码的时候也会有一个很智能的提示

keyof 高级

目前来说是没看懂是咋实现的,已经有点晕掉了

interface Data {
  age: number;
  name: string;
  sex: string;
}

type Options<T extends object> = {
  readonly [key in keyof T]: T[key];
};

type A = Options<Data>

对A来说,就已经实现了Data里每一项都为只读

当然也可以用?修饰使得Data项目都可选,ts还有专门实现了这个功能的方法partial

15 cfg配置文件

tsc --init生成
配置文件里有注释,也可以去翻官方文档

16 namespace

实质是包了一层function
可以嵌套
在最新版本中,推荐使用ES Modules作为模块化的解决方案,而不是过度使用namespace

抽离命名空间
以文件形式export,然后import

简化命名空间
import newName = A.B.C.D的形式为命名空间取别名

ts-node现在认识它了

重名算到一起(和interface一样)

17 三斜线指令

从ts2.0开始,三斜线引用被废弃,推荐使用es6模块语法和import语句来替代
主要用于旧版本中

///

还可以用于声明文件

配置也有点麻烦,不学了

你说得对,但是import是es6模块语法,后面忘了

18 声明文件

declare

to be continued

高级的ts语法不会一点,先补一下es6再回来填这个坑
完结撒花(

你可能感兴趣的:(typescript,typescript,笔记,javascript)