首页 > 其他分享 >TS学习笔记

TS学习笔记

时间:2022-08-30 11:59:24浏览次数:73  
标签:string age dog TS 笔记 number 学习 类型 name

类型

类型 例子 描述
number 1,2,-2 任意数字
string 'hi',"hi" 任意字符串
boolean true,false 布尔值或者true false
字面量 其本身 限制变量的值就是该字面量的值
any * 任意类型
unknown * 类型安全的any
void 空值(undefined) 没有值或者undefined
never 没有值 不能是任意值
array [1,1,2] 任意js数组
object {name:"孙悟空"} 任意js对象
tuple [4,5] 元素,TS新类型,固定长度的数组
enum enum{A,B} 枚举,TS新类型

接口interface与类型别名type

区别:

接口,只能为对象指定类型

类型别名,不仅可以给对象指定类型,实际上可以为任意类型指定别名

//接口
interface  IPerson = {
  name: string
  age: number
  sayHi(): void
}

// 类型别名
type IPerson = {
  name: string
  age: number
  sayHi(): void
}

let person: IPerson = {
  name: '刘老师',
  age: 18,
  sayHi() {}
}

//类型别名
  type NumStr = number | string
	
let numStr: NumStr = 33
let numStr2: NumStr = '66'

字面量类型

思考以下代码,两个变量的类型分别是什么?

let str1 ='Hello Ts'
const str2 : 'Hello Ts'

通过 TS 类型推论机制,可以得到答案:

\1. 变量 str1 的类型为:string。

\2. 变量 str2 的类型为:'Hello TS'。

解释:

\1. str1 是一个变量(let),它的值可以是任意字符串,所以类型为:string。

\2. str2 是一个常量(const),它的值不能变化只能是 'Hello TS',所以,它的类型为:'Hello TS'。

注意:此处的 'Hello TS',就是一个字面量类型。也就是说某个特定的字符串也可以作为 TS 中的类型。

除字符串外,任意的 JS 字面量(比如,对象、数字等)都可以作为类型使用。

let str1 = 'Hello TS'

const str2: 'Hello TS' = 'Hello TS'

let age: 18 = 18

使用模式:字面量类型配合联合类型一起使用。
使用场景:用来表示一组明确的可选值列表。
比如,在贪吃蛇游戏中,游戏的方向的可选值只能是上、下、左、右中的任意一个。
解释:参数 direction 的值只能是 up/down/left/right 中的任意一个。
优势:相比于 string 类型,使用字面量类型更加精确、严谨


function changeDirection(direction: 'up' | 'down' | 'left' | 'right') {}

changeDirection('left')

枚举类型

//枚举
/**
 *enum
 */
enum Gender {
  Male = 0,//可以写=0  也可以不写
  Female = 1,
}

let i1: { name: string; gender: Gender };
i1 = {
  name: "孙悟空",
  gender: Gender.Male,
};
console.log(i1.gender === Gender.Female);
// 枚举:

enum Direction {
  Up,
  Down,
  Left,
  Right
}

function changeDirection(direction: Direction) {}

changeDirection(Direction.Left)

枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值。

枚举:定义一组命名常量。它描述一个值,该值可以是这些命名常量中的一个。

解释:

\1. 使用 enum 关键字定义枚举。

\2. 约定枚举名称、枚举中的值以大写字母开头。

\3. 枚举中的多个值之间通过 ,(逗号)分隔。

\4. 定义好枚举后,直接使用枚举名称作为类型注解。

可以直接使用 . 来访问枚举中的成员

数字枚举 字符串枚举

枚举是 TS 为数不多的非 JavaScript 类型级扩展(不仅仅是类型)的特性之一。

因为:其他类型仅仅被当做类型,而枚举不仅用作类型,还提供值 (枚举成员都是有值的)。

也就是说,其他的类型会在编译为 JS 代码时自动移除。但是,枚举类型会被编译为 JS 代码

enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT'
}

​ ⬇

var Direction;
(function (Direction) {
    Direction["Up"] = "UP";
    Direction["Down"] = "DOWN";
    Direction["Left"] = "LEFT";
    Direction["Right"] = "RIGHT";
})(Direction || (Direction = {}));

说明:枚举与前面讲到的字面量类型+联合类型组合的功能类似,都用来表示一组明确的可选值列表。

一般情况下,推荐使用字面量类型+联合类型组合的方式,因为相比枚举,这种方式更加直观、简洁、高效。

any类型

原则上不推荐使用any类型这会让 TypeScript 变为 “AnyScript”(失去 TS 类型保护的优势)。

因为当值的类型为 any 时,可以对该值进行任意操作,并且不会有代码提示

let obj: any = { x: 0 }

// 访问不存在的属性 或者 赋值
// obj.aaa
// obj.aaa = 10

// 当作函数调用
// obj()

// 赋值给其他类型的变量
// let n: number = obj

// --

// let a
// a = 1
// a = ''
// a()

// function add(num1, num2) {}
// add(1, 2)
// add(1, '2')
// add(1, false)

解释:以上操作都不会有任何类型错误提示,即使可能存在错误!

尽可能的避免使用 any 类型,除非临时使用 any 来“避免”书写很长、很复杂的类型!

其他隐式具有 any 类型的情况:1 声明变量不提供类型也不提供默认值 2 函数参数不加类型。

注意:因为不推荐使用 any,所以,这两种情况下都应该提供类型!

unknown与any

unknown只霍霍自己 赋值给别人是不行的 而any只要跟他沾边都会被霍霍都变成any

unknown就是个类型安全的any 赋值给别人前必须做判断

let e: unknown = 'str';
let s: string;
//unknown 赋值给别人需要先判断类型
if (typeof e === "string") {
  s = e;
}
//或者类型断言
s = e as string;
s = <string>e;


联合类型

let a = "male" | "female"
a = "male";
a = "female";

typeof

void never

主要用于函数返回值的确定

function fn(num): void {
  if (num>0) {
    return; //不应有返回值
  } else {
    return undefined;
  }
}
function fn2(): never{
  throw new Error("出错了");//就是执行不完 一定会出错
}


object 与函数结构的类型声明

一般是不用object 限制太宽泛了

let a1: object;
a1 = {}
a1 = function () {
  
};
//用于指定哪些属性
let b1: { name: string, age?: number }//加上问好表示属性可选
b1 = { name: '孙悟空' }
let c1: { name: string, [propName: string]: any }// [propName: string]: any表示可以有任意类型的属性
c1 = { name: "猪八戒", age: 18, gender: "male" }
//定义函数的参数结构 的类型声明
let d1: (a: number, b: number) => number;
d1 = function (a: number, b: number) { return a + b; };

array

//数组
let e1: string[];//表示字符串数组
e = ['a', 'b', 'c', 'd'];
let f1: number[];
let g1: Array<number>;

元组

长度固定的数组

//元组
/**
 * 语法: [类型,类型,类型]
 */
let h1: [string, string, number];
h1 = ["hello", "world", 123];

或 | 和 与&


// |  表示或   & 表示且

let j1: { name: string } & { age: number }
j1={name: "孙悟空",age:18}

编译选项

tsc app.ts -w

-w watch模式 只监视app.ts

使用tsc 编译此项目下的全部ts文件 前提是得由tsconfig.json文件 即使这个文件为空json也会按照默认的选项来编译!

webpack打包TS

package.json 需要哪些包

{
  "name": "ts-webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack  serve --open  "
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.18.13",
    "@babel/preset-env": "^7.18.10",
    "babel-loader": "^8.2.5",
    "clean-webpack-plugin": "^4.0.0",
    "core-js": "^3.24.1",
    "html-webpack-plugin": "^5.5.0",
    "ts-loader": "^9.3.1",
    "typescript": "^4.7.4",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.10.0"
  }
}

webpack.config.js 定义打包的方式

//引入路径包
const path = require("path");
//引入一个插件包
const HTMLWebpackPlugin = require("html-webpack-plugin");

//引入clean插件
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
  //添加模式
  mode: "development",
  //指定入口文件
  entry: "./src/index.ts",
  //指定打包文件所在目录
  output: {
    //指定目录
    path: path.resolve(__dirname, "dist"),
    //指定名字
    filename: "index.js",
    //配置环境兼容问题
    environment: {
      arrowFunction:false
    }
  },
  //指定打包时要用到的模块
  module: {
    rules: [
      {
        //test指定的是规则生效的文件
        test: /\.ts$/, //匹配以ts结尾的文件
        //use 要使用的loader  数组中的内容从后往前执行
        use: [
          {
            //设置加载器
            loader: "babel-loader",
            //设置babel
            options: {
              //设置预定义的环境
              presets: [
                [
                  //指定环境的插件
                  "@babel/preset-env",
                  //配置信息
                  {
                    //要兼容的默认浏览器
                    targets: {
                      //浏览器版本
                      "chrome": "58",
                      "ie":"11"
                    },
                    //指定corejs的版本
                    "corejs": "3",
                    //使用corejs的方式
                    "useBuiltIns": "usage"
                  }
                ]
              ] 
            },
          },
          "ts-loader",
        ],
        //exclude 排除哪些文件
        exclude: /node-modules/,
      },
    ],
  },
  //配置webpack的插件
  plugins: [
    new CleanWebpackPlugin(),
    new HTMLWebpackPlugin({
      // title: "这是一个自定义的title",
      template: "./src/index.html",
    }),
  ],
  //用来设置引用模块
  resolve: {
    extensions: [".ts", ".js"],
  },
};

tsconfig.json ts的编译方式

{
  "compilerOptions": {
    "module": "ES2015",
    "target": "ES2015",
    "strict": true
  }
}

//使用class关键字来定义一个类
/**
 *   属性  
 *   方法
 */
class Person{
  //实例属性
  name: string = "孙悟空";
  //在属性前加关键字static可以定义类属性(静态属性)即不需要创建实例就可访问的属性
  static age: number = 18;
  //只读属性
  readonly gender: string = "male";

  //实例方法
  say() {
    console.log('hello')
  }
  //静态方法
  static run() {
    console.log('run')
  }

}
const per = new Person();
console.log('per.name', per.name);
console.log('per', per);
per.say();  
console.log('Person.age', Person.age)
Person.run();

构造函数与this

class Dog{
  name: string;
  age: number;
  //构造函数
  constructor(name: string, age: number) {
    console.log('构造函数执行了',this)
    this.name= name
    this.age= age
  }

  bark() {
    console.log('wangwangwang')
  }
}
const dog = new Dog('xiaohei',4);
console.log('dog',dog)

类的继承

(() => {
  class Animal {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
    sayHello() {
      console.log(`${this.name}sayHello`);
    }
  }

  class Dog extends Animal {
    sayHello(): void {
      console.log("wangwangwang"); //子类覆盖掉父类的方法的形式叫重写
    }
  }

  class Cat extends Animal {
    run() {
      console.log(`${this.name}run`);
    }
  }
  const dog = new Dog("旺财", 5);
  const cat = new Cat("咪咪", 3);
  console.log("cat", cat);
  console.log("dog", dog);
  dog.sayHello();
  cat.sayHello();
  cat.run();
})();

super

(() => {
  class Animal {
    name: string;

    constructor(name: string) {
      this.name = name;
  
    }
    sayHello() {
      console.log(`${this.name}sayHello`);
    }
  }

  class Dog extends Animal {
    age: number;
    constructor(name: string, age: number) { 
      super(name);//必须先调用父类的构造函数
      age = this.age;
    }

    sayHello(): void {
      super.sayHello(); //super表示当前类的父类
    }
  }

  const dog = new Dog('旺财',1);
  dog.sayHello();
})();

抽象类

(() => {
  abstract class Animal {
    //我们不希望直接用Animal来创建实例,我们只需要让它是一个超类 用来被继承
    //所以我们给它加上abstract   那么这个类就只能被继承    不能用它创建实例
    //抽象类可以添加抽象方法
    name: string;

    constructor(name: string) {
      this.name = name;
    }
    //抽象方法只能在抽象类里定义  抽象方法没有方法体
    //子类必须对抽象方法进行重写
    abstract sayHello(): void;
  }

  class Dog extends Animal {
    //非抽象类继承抽象类 必须重写父类中的抽象方法
    sayHello(): void {
      console.log("汪汪汪");
    }
  }

  const dog = new Dog("旺财");
  dog.sayHello();
})();

接口

(() => {
  /**
   * 对于类型声明(类型别名) 只能声明一次
   *
   * 对于接口 可以重复声明  多次声明那么创建的实例应把接口中的定义的都实现
   *           接口可以限制类的结构
   *           接口只定义类的结构不定义类的实际值
   *           接口的所有方法都是抽象方法
   *
   *
   *
   */
  //描述一个对象的类型   类型别名
  type myType = {
    name: string;
    age: number;
  };
  let obj: myType = {
    name: "sss",
    age: 1,
  };

  /**
   * 接口用来定义一个对象的结构
   * 用来定义一个类中应该包含哪些属性和方法
   */
  interface myInterface {
    name: string;
    age: number;
  }
  interface myInterface {
    gender: string;
    sayHello(): void;
  }

  let obj1: myInterface = {//当作类型使用
    name: "aaa",
    age: 2,
    gender: "male",
    sayHello() {
      console.log("hello");
    },
  };

  //实现接口
  class Myclass implements myInterface { 
    name = '孙悟空';
    age = 18;
    gender = 'male';
    sayHello() { 
      console.log("嘿嘿")
    }
  }
})();

属性的封装

private getter setter

(() => {
  class Person {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
  }

  let per = new Person("孙悟空", 18);
  console.log("per", per);
  per.name = "猪八戒";
  per.age = -18;
  console.log("per", per); //可以任意修改 年龄能有负数嘛?
  /**
   * 上面的属性是在对象中设置的,属性可以任意的被修改
   *  属性可以任意被修改将会导致对象中的数据会变得非常不安全
   */
  class Animal {
    /**q
     * 可以在属性前添加修饰符
     */
    public name: string; //公共属性可以在任意位置(访问)更改  默认就是public
    private age: number; //私有属性 只能在类内部(访问)修改
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
    //getter 添加方法让私有属性可以在外部访问
    getAge() {
      return this.age;
    }
    //setter 设置属性
    setAge(value: number) {
      if (value > 0) {
        this.age = value;
      }
    }
  }
  let dog = new Animal("旺财", 2);
  console.log("dog", dog);
  console.log("dog.getAge()", dog.getAge());
  dog.setAge(-8);
  console.log("dog", dog); //改不了
})();

protected 与 constructor 语法糖

(() => {
  class Person {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
  }

  let per = new Person("孙悟空", 18);
  console.log("per", per);
  per.name = "猪八戒";
  per.age = -18;
  console.log("per", per); //可以任意修改 年龄能有负数嘛?
  /**
   * 上面的属性是在对象中设置的,属性可以任意的被修改
   *  属性可以任意被修改将会导致对象中的数据会变得非常不安全
   */
  class Animal {
    /**q
     * 可以在属性前添加修饰符
     */
    public _name: string; //公共属性可以在任意位置 包括子类 (访问)更改  默认就是public
    private _age: number; //私有属性 只能在类内部(访问)修改
    //protected   受保护的属性,只能在当前类和当前类的子类中访问
    constructor(name: string, age: number) {
      this._name = name;
      this._age = age;
    }
    // //getter 添加方法让私有属性可以在外部访问
    // getAge() {
    //   return this.age;
    // }
    // //setter 设置属性
    // setAge(value: number) {
    //   if (value > 0) {
    //     this.age = value;
    //   }
    // }

    //ts中设置获取属性 设置属性 的方法  不会改变访问数据的方法
    /**
     * 不是特别复杂的修改时  一般用不到
     */
    get age() {
      return this._age;
    }
    set age(value: number) {
      if (value > 0) {
        this._age = value;
      }
    }
  }
  let dog = new Animal("旺财", 2);
  // console.log("dog", dog);
  // console.log("dog.getAge()", dog.getAge());
  // dog.setAge(-8);
  console.log("dog.age", dog.age);
  // console.log("dog", dog); //改不了
  dog.age = 8;
  console.log("dog", dog);

  /**
   * 语法糖
   */

  class C {
    //得用public
    constructor(public name: string, public age: number) {}
  }
  let c = new C("666", 6);
  console.log("c", c);
})();

泛型

(() => {
  function fn(a: any): any {
    return a;
  }
  /**
   * 在定义函数或是类时遇到类型不明确的  可以使用泛型
   *
   */
  function fn1<T>(a: T): T {
    //我不知道a到底是是么类型但是我知道 返回值和入参的类型时相同的
    return a;
  }
  fn1(10); //自动推断
  fn1<string>("test"); //类型断言

  function fn2<T, K>(a: T, b: K): T {
    console.log("b", b);
    return a;
  }
  fn2(123, "test");
  fn2<number, string>(333, "test");

  interface Test {
    length: number;
  }
  //泛型T得是Test的实现类(子类)
  function fn3<T extends Test>(a: T): number {
    return a.length;
  }
  fn3([1, 2, 2]); //传入的参数的类型得是Test接口的实现类
})();

仓库地址:https://gitee.com/bbigger004/tslearn.git

标签:string,age,dog,TS,笔记,number,学习,类型,name
From: https://www.cnblogs.com/bbigger004/p/16638770.html

相关文章

  • 函数(知乎)学习笔记
    函数知乎系列笔记✏️在知乎上看到一个视频专栏,讲的`特别好`,函数之前跟着B站老男孩的视频过了一遍,再听知乎这套视频,温故而知新,又发现很多盲点了!知乎这套简短的视频言简意......
  • vivo前端智能化实践:机器学习在自动网页布局中的应用
    作者:vivo互联网前端团队-SuNing在设计稿转网页中运用基于self-attention机制设计的机器学习模型进行设计稿的布局,能够结合dom节点的上下文得出合理的方案。一、背景......
  • HCIA学习笔记二十六:手工负载分担模式二层链路聚合
    一、链路聚合的应用场景• 链路聚合一般部署在核心结点,以便提升整个网络的数据吞吐量。二、链路聚合• 链路聚合能够提高链路带宽,增强网络可用性,支持负载分担。三......
  • Linux学习笔记5——目录和文件,时间
    Linux学习笔记5——目录和文件一、目录和文件:根目录:/,目录的最后面是文件。文件名是由目录+文件名组成的。当前目录:登录Linux后,一定处于目录树的某个目录中,这个目录称......
  • 手机给笔记本投屏?
    将手机和笔记本连接同一个wifi在电脑上按【win+i】进入【设置】——【系统】——【投影到此电脑】点击【可选功能】点击【查看功能】搜索【无线显示器】回到【投......
  • 为什么常识知识不(也不能)学习
    为什么常识知识不(也不能)学习常识(背景)知识,至少是我们在语言理解过程中获取和传递的知识:(i)不能通过处理大量文本来学习,因为这些知识从未在文本中明确说明——而你找不到不......
  • 机器学习算法在 IRIS 数据集上的可视化与应用
    机器学习算法在IRIS数据集上的可视化与应用五eri集由3种鸢尾花(IrisSetosa、IrisVirginia、IrisVersicolar)组成,每个品种有50个样本,共有150个数据。该数据集......
  • 自我监督学习
    自我监督学习自监督学习(SSL)正在迅速缩小与监督方法的差距。最近,拓宽自我监督学习视野的主要参与者之一FacebookAIResearch(FAIR)引入了SEER。SEER是一个1.3B......
  • java 线程池 学习记录
    线程池构造函数参数有哪些核心线程池最大线程数空闲非核心线程存活时长空闲非核心线程存活时长单位阻塞队列线程生产工厂拒绝执行处理类execute和s......
  • java并发 学习记录
    哪些方法会抛出InterruptedException异常?Thread类怎么处理异常可以在Thread中设置异常处理类(实例方法)--setUncaughtExceptionHandlerThread.interupt()方法可以......