关于typescript:TypeScript使用

TS学习应用

一、ts环境搭建

1.ts简介

typescript 是 javascript 的一个超集,在js的根底上,增加了变量类型的限度

2.环境

1.装置node:https://nodejs.org/dist/v16.1…
2.应用包管理器装置ts编译器typescript

npm install -g typescript

编译运行:

// tsc =====> typescript compiler

// 编译 将指定ts编译编译成.js,tsc hell.ts -w可实现文件批改后的主动从新编译
tsc hello.ts

// 运行编译后的.js
node hello.js

3.可应用ts-node,一次性实现ts的编译与运行

// 装置ts-node
npm install -g ts-node

// 运行ts
ts-node hello.ts

4.应用webpack搭建hmr环境,实时的看到ts编译运行成果。

二、ts的根本类型

1.类型申明的根本应用形式:

let a: number;
let b: string = "hello";
function fn(x:number, y:string):void{
    console.log(x, y);
}
let sym:symbol = Symbol("symbol");

2.罕用类型

number、string、boolean类型:

let a:string;
let b:boolean;
function fu():number{
    return 1;
}
let nu:null = null;
let und:undefined = undefined;

字面量类型:

// 间接应用字面量进行类型申明,应用时相当于常量
// 能够应用 | 来连贯多个类型
let sex: "male" | "female";
sex = 'male';

// 字面量推断
type MethodType = "get" | "post" | "put" | "delete" | "patch";
let get: string = "get";
function request(method: MethodType): void {}
request(get as MethodType);

any类型:

//任意类型,等同于没有类型限度了
let d: any;    // 显示any类型
let m;        // 隐式any类型

unknown类型:

let s: string;

// unknown 实际上就是类型平安的any
// unknown 类型的变量,不能间接赋值给其它类型的变量
let e: unknown = "hello";

// 将unknown赋值给其它类型
// 办法一:类型判断
if(typeof e === "string"){
    s = e;
}

// 办法二:类型断言
// s = (<string>e);
s = e as string;

void与never:

// void 返回值为空值
function fn():void{
    return undefined||null;
}

// never 不会有返回值,罕用于用来报错的函数
function fn2():never{
    throw new Error('error');
}

object类型:

// 对象申明一:
let a: object; // 能够是任何类型的对象,个别不实用

// 对象申明二:
let b: {        //对象类型申明,蕴含属性限度
    name: string,
    age? : number        // ? 示意改属性可选
};

b = {
    name: 'jiangjiangwa',
    age: 18
}

// 对象申明三:
let c:{
    name: string,

    // 任意的字符串属性名,任意类型的any属性值
    [x: string]: any
}

函数构造类型申明:

// (形参:类型,形参:类型)=>返回值类型
let f :(arg1:number,arg2:number)=>number

f = function(n1,n2):number{
    return n1+n2;
}

array类型:

// 示意数字数组
let a:number[];
let b:Array<number>;

const names: string[] = ["John", "Jane", "Mary"];
names.forEach((item)=>{ // 这里的item能够不增加类型注解
    console.log(item);
})

tuple固定长度的数组:

let h:[number,string];
h = [123, "world"];

// 应用示列
function useState<T>(state: T) {
  let currentState = state;
  const changeState = (newState: T) => {
    currentState = newState;
  };

  const tuple: [T, (newState: T) => void] = [currentState, changeState];
  return tuple;
}

const [counter,setCounter] = useState(0);

enum枚举类型:

enum Gender {
    Male,
    Female,
}

console.log(Gender)
let i: { name: string; gender: Gender };
i = {
  name: "孙悟空",
  gender: Gender.Male, // 'male'
};

联结类型:

let a:number|string;
a = 1;

let b : {name:string}&{age:number};

b = {
    name:'jiangjiangwa',
    age:18
}
type IdType = string | number;
function printId(id: IdType) {
  // 外部须要对联结类型做操作时,须要应用typeof 先做类型判断
  // narrow type (放大范畴)
  if(typeof id === 'string') {
    console.log(id.toUpperCase());
  }else{
    console.log(id);
  }
}
printId('abs');

穿插类型

type MyType = number & string; // 等同于 never 类型

interface Colorful {
  color: string;
}

interface IRun {
  running: () => void;
}

type NewType = Colorful & IRun;
const obj: NewType = {
  color: "red",
  running() {},
};

类型的别名

type myType = string | number;

let k:myType = 'hello';

类型断言

const imgEle = document.getElementById("img_show") as HTMLImageElement;
imgEle.src = './img/1.jpg';


class Person{};
class Student extends Person{
  studying(){
    console.log('studying');
  }
}
function sayHello(person: Person){
  (person as Student).studying();
}
sayHello(new Student());

非空断言

function printMessage(message?:string){
console.log(message!.length)

}
可选链
是ES11(ES2020)中减少的个性,它的作用是当对象的属性不存在时,会短路,间接返回undefined,如果存在,那么才会继续执行

function printMessage(message?:string){
  console.log(message?.length)
}

// 编译失去的js
function printMessage(message) {
    console.log(message === null || message === void 0 ? void 0 : message.length);
}

??操作符
空值合并操作符(??)是一个逻辑操作符,当操作符的左侧是 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数,与||应用的区别,??值判断null、undefined,而||会判断所有假值,蕴含0、””、false、null、undefined

let message: string |null = "Hello World";
const content = message ?? '你好哇,李银河';
// const content = message || '你好哇,李银河';  
console.log(content);

三、ts编译选项

初始化ts编译配置文件tsconfig.json

tsc --init    

应用tsconfig.json后,可批量编译整个我的项目的所有ts文件
// tsc 间接编译所有ts文件

// tsc -w 编译所有ts文件并监督所有ts文件

tsconfig.json配置参数阐明:

{
  /* 
  tsconfig.json 是ts编译器的配置文件,ts编译器会读取该文件,并且依据该文件的配置来编译ts文件。
    "include": 用来指定那些ts文件须要被编译
      门路:**  递归匹配任意子目录
            *  示意任意文件
            ?  匹配一个任意字符(不包含目录分隔符

   */
  "include": ["./src/**/*.ts", "./src/**/*.js", "./main.ts"],
  //  "exclude": ["./node_modules"],  //有默认值
  "compilerOptions": {
    //target 用来指定ts被编译为的ES的版本
    "target": "ESNext", //ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext
    "module": "es2015", //指定编译为模块化标准

    //lib 用来指定哪些库是须要被蕴含在编译后的js中  能够指定多个
    // "lib": ["dom","es6"] // 默认不变

    "outDir": "./dist", //指定编译后的js文件输入目录

    // 设置outFile后,所有全局作用域中的代码,回合并到对立的js文件中,个别应用打包工具实现
    // "outFile": "./dist/bindle.js",

    // 是否对js文件进行编译,默认是false
    "allowJs": true,

    // 是否查看js代码的语法,默认是false,须要在tsconfig.json中设置"allowJs": true
    "checkJs": true,

    "removeComments": false, //是否移除正文,默认是false

    // 不生成编译后的js文件,默认是false.但只须要对ts进行语法查看时,应用
    "noEmit": false,

    // 所有严格查看的总开关
    "strict":true,

    // 产生谬误时,不生成编译文件,默认是false
    "noEmitOnError": true,

    "alwaysStrict": true, //是否开启严格模式,默认是false,当应用了模块化语法时,默认开启了严格模式

    // 不容许应用隐式any类型,默认是false
    "noImplicitAny": true,

    // 不容许不明确类型的this
    "noImplicitThis": true,

    "strictNullChecks": false, //是否开启严格空值查看,默认是false

  } 
}

四、面向对象

1.类的应用

// 应用class关键字定义一个类
/* 
对类的属性(实例属性、动态属性)和办法进行形容
在对类的静态方法或实列属性进行赋值时,须要被限度
 */

class Person {
  // 动态属性
  static readonly county: string = "中国";

  // 实例属性
  name: string = "default";
  age = 18;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  // 实列办法
  //   say: (a: number, b: number) => void = function (a, b) {
  //     console.log(a + b);
  //   };
  say(a: number, b: number): number {
    return a + b;
  }
}

const person = new Person("John", 30);

类做类型:

class Person {
  name:string = '123'

  eating(){}
}
// 须要跟类的实例,具备雷同的构造与类型
const p1:Person = {
  name:'jiang',
  eating(){}
}
function printPerson(p:Person){
  console.log(p.name);
}

printPerson({
  name:'jiang',
  eating(){}
})

extends应用:
凋谢关闭准则(OCP,Open Closed Principle),批改是关闭的, 对扩大凋谢。

class Animal {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }
    say() {
      console.log("I am a animal");
    }
  }

  class Dog extends Animal {
    constructor(name: string, age: number) {
      super(name, age);
    }
  }

  class Cat extends Animal {
      say(): void {
          console.log('miao miao miao')
      }
      // 没有重写contructor办法,创立的实例会调用父类的构造函数
  }

Cat.prototype.__proto__ = Animal.prototype

抽象类abstract:

(function () {
    // 不能用来创立实列,专门用来继承的类
    // 能够增加形象办法
  abstract class Animal {
    name: string;
    age: number;
    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }

    // 形象办法,只能定义在抽象类中,子类必须实现该办法
    abstract say(): void;
  }

  class Dog extends Animal {
    constructor(name: string, age: number) {
      super(name, age);
    }
    say(): void {
        console.log('wang wang wang')
    }
  }

  class Cat extends Animal {
    say(): void {
      console.log("miao miao miao");
    }
    // 没有重写contructor办法,创立的实例会调用父类的构造函数
  }
})();

接口interface

const obj: myInterface = {
    name: "John",
    age: 30,
    gender?: "男",
    say() {
      console.log("jiang");
    },
  };
  console.log(obj);

  // 构造用来定义类的构造,也可当作类型申明应用
  // 可反复申明(拓展原有接口性能),类型限度叠加,接口中,所有办法,都是形象办法
  // 实现接口,就是满足接口的要求
  interface myInterface {
    name: string;
    age: number;
  }

  interface myInterface {
    gender: string;
    say(): void;
  }

  class Person implements myInterface {
    name: string;
    age: number;
    gender: string;

    constructor(name: string, age: number, gender: string) {
      this.name = name;
      this.age = age;
      this.gender = gender;
    }
    say(): void {
      throw new Error("Method not implemented.");
    }
  }
  console.log(new Person('jiang',18,'男'));

// 接口应用练习
interface FrontLanguage {
  [key: number]: string;
}

const frontLanguage: FrontLanguage = { 
  1: "HTML", 
  2: "CSS", 
  3: "JavaScript" };

interface LengthInterface {
  'length': number;
}

const obj: LengthInterface = { length: 10 };

//接口定义函数类型
interface CalcFunc {
  (num1:number,num2:number):number;
}

const add:CalcFunc = (num1,num2) =>{
  return num1 + num2;
}

接口的继承

interface Person {
  name: string;
  eating: () => void;
}
interface Animal {
  runing: () => void;
}

interface Student extends Person, Animal {
  sno: number;
}

字面量赋值freshness擦除操作:

interface IPerson {
  name: string;
  eating: () => void;
}

const obj = {
  name: "John",
  eating: () => {},
  age: 18,
};
// 间接将字面量赋值给变量 会报错
// p: IPerson = {
//   name: "John",
//   eating: () => {},
//   age: 18,
// }
const p: IPerson = obj;
console.log(p);

属性封装:

(function () {
  class Person {
    private _name: string;

    get name(): string {
      return this._name;
    }
    set name(value: string) {
      if (this.name.startsWith("张")) {
        this._name = value;
      } else {
        this._name = "张" + value;
      }
    }
    age: number;
    constructor(name: string, age: number) {
      this._name = name;
      this.age = age;
    }
  }

  let p = new Person("John", 30);
  console.log(p);

  p.name = "Tom";
  p.age = 10;
  console.log(p);
})();

class+属性封装的简写:

  class Dog {
    constructor(public name: string, private age: number) {}

    // 等同于
    // public name: string;
    // private age: number;
    // constructor(name: string, age: number) {
    //   this.name = name;
    //   this.age = age;
    // }
  }

泛型:
形式一:通过 <类型> 的形式将类型传递给函数;
形式二:通过类型推到,主动推到出咱们传入变量的类型:

function foo<T>(arg:T):T { // 这里时,会将arg类型推导进去,赋值给T
    return arg;
}
foo<string>('123');

foo(123);

/* 
    在定义函数或是类是,如果遇到类型不明确就能够应用泛型
    定义了一个示意类型的变量
 */

interface Inter {
  length: number;
}

/* 
泛型限度,须要合乎接口类型限度
T extends Inter 示意泛型T必须是Inter实现类(子类)
 */
function fn2<T extends Inter>(a: T): number {
  return a.length;
}

fn2("1");

// 泛型接口
interface IFoo<T> {
  initValue: T;
  valueList: T[];
  getValue(): T;
}

class Foo implements IFoo<number> {
  initValue: number = 0;
  valueList: number[] = [1, 3, 4, 5];
  getValue(): number {
    return this.initValue;
  }
}
// 泛型类
class Point<T> {
  x: T;
  y: T;
  constructor(x: T, y: T) {
    this.x = x;
    this.y = y;
  }
}
let point: Point<number> = new Point<number>(1, 2);

罕用泛型名称:
T:Type的缩写,类型
K、V:key和value的缩写,键值对
E:Elment的缩写,元素
O:Object的缩写,对象

五、模块化

命名空间在TypeScript晚期时,称之为外部模块,次要目标是将一个模块外部再进行作用域的划分,避免一些命名抵触的问题。

export namespace time { // 这里时模块的导出 在别的模块应用
  export function format(time: string) { // 这里是命令空间的导出,模块内应用
    return "3033-01-01T" + time + ":00.000Z";
  }

  function foo(){

  }
}

export namespace price {
  export function format(price: number) {
    return price.toFixed(2);
  }
}

time.format('2-2')
// time.foo() // error: foo is not exported,没有在明明空间导出的,只能在命名空间外部应用

六、类型申明

另外的一种typescript文件:.d.ts文件
p 咱们之前编写的typescript文件都是 .ts 文件,这些文件最终会输入 .js 文件,也是咱们通常编写代码的中央;
p 还有另外一种文件 .d.ts 文件,它是用来做类型的申明(declare)。 它仅仅用来做类型检测,告知typescript咱们有哪些类型;

1.内置类型申明
内置类型申明是typescript自带的、帮忙咱们内置了JavaScript运行时的一些标准化API的申明文件;
p包含比方Math、Date等内置类型,也包含DOM API,比方Window、Document等;
typescript/lib/*.d.ts文件

2.内部定义类型申明
应用一些库(比方第三方库)时,须要的一些类型申明。
这些库通常有两种类型申明形式:
a.本人库中进行类型申明(编写.d.ts文件),比方axios下index.d.ts文件
b形式二:通过社区的一个私有库DefinitelyTyped寄存类型申明文件 p该库的GitHub地址:https://github.com/Definitely…
该库查找申明装置形式的地址:https://www.typescriptlang.or…
比方咱们装置react的类型申明: npm i @types/react –save-dev

3.自定义类型申明
自定义lodash库的申明

// index.ts 中
import _ from 'lodash';

console.log(_.join(['99, 2,','fjk']));


types-> _lodash.d.ts文件中
declare module 'lodash' {
    export function join(arr:any[])
}


// 申明其它类型
// 申明函数、类、接口、类型、对象、变量等
declare function add(a:number,b:number):number;
declare class Person {
    name:string;
    age:number;
    constructor(name:string,age:number);
}
declare interface IPerson {
    name:string;
    age:number;
}
declare let p:IPerson;
// 申明文件
declare module '*.jpg' 
declare module '*.png'
declare module '*.vue' {}
// 申明命名空间,当间接应用cdn的形式导入时,能够应用
declare namespace ${
    export function ajax(url:string,options:any):Promise<any>
}
 

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理