TypeScript记录

这是一个乱七八糟的笔记

typeScript和React webpack结合

下载文件

  1. npm i --save react react-dom @types/react @types/react-dom @types/前缀表示我们额外要获取react和react-dom的声明文件。
  2. npm i --save-dev typescript awesome-typescript-loader source-map-loader ts-loader awesome-typescript-loader可以让Webpack使用TypeScript的标准配置文件tsconfig.json编译TypeScript代码。 source-map-loader使用TypeScript输出的sourcemap文件来告诉webpack何时生成自己的sourcemaps.这就允许你在调试最终生成的文件时候就好像在调试TypeScript源码一样 ts-loader 将typescript转换成JavaScript;
  3. 根目录下创建tsconfig.json文件
{
  "compilerOptions": {
    "outDir": "./dist/", //编译js的输出目录
    "sourceMap": true, // 编译是否生成对应的source map文件
    "noImplicitAny": true, //强类型检查,无法推断类型时候,提示错误
    "module": "commonjs", // 定义遵循的JavaScript模块规范
    "target": "es5", //遵循的标准
    "jsx": "react",
    "experimentalDecorators": true, // 启用实验性的装饰器特性
  },
  "include": [
    "./src/**/*" // 需要包含编译的目录
  ]
}
复制代码

创建webpack.config.js

module.exports = {
  entry: "./src/index.tsx",
  output: {
    filename: "bundle.js",
    path: __dirname + "/dist"
  },
  devtool: "source-map",
  resolve:{
    extensions: [".ts", ".tsx", ".js", ".json"]
  },
  module: {
    rules: [
      { 
        test: /\.tsx?$/,
        loader: "awesome-typescript-loader"
      },
      {
        enforce: "pre",
        test: /\.js$/,
        loader: "source-map-loader"
      }
    ]
  },
  externals: {
    "react": "React",
    "react-dom": "ReactDOM"
  }
}
复制代码

数据类型

ts中的数据类型有:Number数值类型,string字符串类型,Boolean布尔类型,enum枚举类型, any任意类型,void空类型,Array数组类型,Tuple元祖类型,Null空类型。

引用类型-数组
  1. 声明数组 let arr:number = [];
  2. 给数组赋值
字面量赋值:let arr: number = [1,2,4]
构造函数赋值: let arr:Array<number> = new Array(1,2,3)
复制代码

ts中,指定数据类型的数组只能存贮同一类型的数组元素

  1. 元祖 元祖是特殊的数组,元祖类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。
let arr:[string,number];
arr = ['12', 2];
arr = [2,'12'] // 报错
复制代码
字符串

基本类型字符串:用双引号或者单引号括起来的一串字符串 引用类型字符串:用new实例化的String类型

let jsan:string = '发就是电话';
let jsanpan:String = new String('1333吃')
console.log(jsan);
console.log(jsanpan); // 打印出的String {'1333吃'}
复制代码
引用类型-日期对象

日期对象是Date实例,可用构造函数的方法进行创建,声明这个日期变量时候,也要标明它的类型是Date,eg: let d:Date = new Date('2018/09/09 05:30:00')

引用类型-正则表达式

两种方式:一种是字面量方式,一种是new关键字;常用test和exec测试字符串匹配

let str:string = 'abcdefg';
let reg:RegExp = /ab/g;
let result:boolean = reg.test(str);
console.log(result); // true
let str2 = 'dapangzishuai'
let reg2:RegExp = new RegExp("dapang",'gi')
let reg3:RegExp = new RegExp("aaa",'gi')
let result:any = reg2.exec(str2);
let result2 = reg3.exec(str2); 
console.log(result) //["dapang", index: 0, input: "dapangzishuai", groups: undefined]
console.log(result2) // null
复制代码
命名空间

为了让程序之间更有层次,变量之间互不干扰,利用命名空间来区分,成员需要用export导出

namespace a {
  export class An {
    name:string = '安安'
    talk() {
      console.log('女生安安')
    }
  }
}
namespace b {
 export class An {
   name:string='安安'
   talk() {
     console.log('男生安安')
   }
 }
}
let an1:a.An = new a.An();
let an2:a.An = new b.An();
console.log(an1.talk(),an2.talk(), '这是啥啊')
复制代码

数据类型

ts中的数据类型有:Number数值类型,string字符串类型,Boolean布尔类型,enum枚举类型, any任意类型,void空类型,Array数组类型,Tuple元祖类型,Null空类型。

变量声明

默认值:默认值可以让你在属性为undefined的时候使用缺省值

function keepWholeObject(whoeObject: { a: string, b?: number }) {
  let { a, b=101 } = whoeObject
  console.log(a,b,'123是')
}
keepWholeObject({ a :'12', b : 10 });
复制代码

函数声明:

function f({ a, b } = { a: "", b: 0 }): void{
  console.log(a, b, 'ab是');
}
f();
复制代码

typeScript的接口

  1. 接口-interface eg: interface LabelledValue { label: string; }代表一个label属性类型为string的对象,如果不满足的话直接报错
  2. 可选属性 与普通的接口定义差不多,只是会在属性名字后面加个?符号 eg:interface LabelledValue { label?: string; color?: string; } 优点:可以对可能存在的属性进行预定义,如果有用到了不存在的属性会报错
  3. 只读属性-readonly 在属性名前用readonly来指定只读属性
interface Point {
  readonly x: number;
  readonly y: number;
}
let point : Point = {
  x: 10,
  y: 10
}
// point.x = 5; 报错,因为是只读属性,不可以进行修改
复制代码
// ReadonlyArray<T>类型,把所有可变方法去掉了,确保数组创建后再也不能被修改
let ro: ReadonlyArray<number> = [1,2,3,4];
ro[0] = 12; 报错,属性只读不可修改
ro.push(4) 报错,ReadonlyArray上没有push这个方法
let a: number[] = [1,2,3,4];
let b: ReadonlyArray<number> = a;
a = b //报错
a = b as number[]; //类型断言重新写,不报错
复制代码

判断是用const还是readonly,看他的用途,如果是变量使用的话用const,属性使用则用readonly

  1. 额外的属性检查

1.避开它的检查,用类型断言的方式 eg: let mySquare = createSquare({colour: "red", width: 100} as SquareConfig) 即使SquareConfig中没有colour这个属性,也不会报错

2.避开它的检查,用索引签名的方式 [propName: string]: any;

3.避开它的检查,将这个对象赋值给另一个变量,squareOptions不会经过额外属性检查 let squareOptions = { colour: 'red'}; let mysquare = createSquare(squareOptions);

  1. 函数类型 如下:函数类型时候,函数的参数名可以不与接口里定义的名字匹配,而且定义的属性值也可以不写。
interface SearchFunc {
  (source: string, subString: string) : boolean;
}
let mySearch: SearchFunc;
mySearch = function(source, subString) {
  let result = source.search(subString);
  return result > -1;
}
复制代码
  1. 可索引的类型 可索引类型具有一个索引签名,描述了对象索引的类型,还有相应的索引返回值类型; 如下,这个索引签名表示当用number去索引StringArray时候会得到string类型的返回值
interface StringArray {
  [index: number]: string;
}
let myArray: StringArray;
myArray = ['Bob', 'Fred'];
let myStr: string = myArray[0];
复制代码
  1. 类类型

静态属性:通过static关键字可以声明类型的静态属性。

  1. 接口的继承 通过implements关键字继承,接口的继承可以多次继承
interface Animal {
  name: string;
  eat(): void;
}
interface Person extends Animal {
  use(): void;
}
class Dog implements Person {
  name: string;
  constructor(theName: string) {
    this.name = theName;
  }
  eat() {
    console.log(`${this.name}吃`)
  }
  use() {
    console.log(`${this.name}胖`)
  }
}
let dog: Person;
dog = new Dog('筛子');
dog.eat();
dog.use();
复制代码
  1. 混合类型
  2. 接口继承类
class Control {
  private state: any;
}
interface SelectableControl extends Control {
  select(): void;
}
class Button extends Control implements SelectableControl {
  select() {

  }
}
class TextBox extends Control {};
// SelectableControl包含了Control的所有成员,包括私有成员,所以Control的子类才可以实现SelectableControl内的接口。Image不是SelectableControl的子类,所以如下写法会报错
// class Image  implements SelectableControl {
//   select(){}
// } //报错
class Image extends Control implements SelectableControl {
  select(){}
} //不报错
复制代码

类class

  1. 如下:Animall是基类,Cat是派生类,Cat派生自基类Animall,通过extends关键字。派生类叫子类,基类通常叫超类。 类的继承
class Animall {
  name: string;
  constructor(theName: string) {
    this.name = theName;
  }
  eat() {
    console.log(`动物叫${this.name}`)
  }
}
let animall = new Animall('小狗');
animall.eat();
class Cat extends Animall{
  constructor(theName: string) {
    super(theName);
  }
  eat() {
    super.eat();
    console.log('吃狗粮')
  }
}
let cat: Animall;
cat = new Cat('猫');
cat.eat();
class People extends Animall {
  constructor(theName: string) {
    super(theName);
  }
  eat() {
    super.eat();
    console.log(`${this.name}拒绝吃狗粮`);
  }
}
let people: Animall;
people = new People('人');
people.eat();
复制代码

子类通过关键字extends继承,通过super方法调用基类的方法,也可以重写基类的方法。 public: 公有属性,可赋值 protected: 受保护属性,无法赋值 private: 私有属性,无法赋值 protected成员在派生类中仍然可以访问,而private成员在派生类中也不可以访问。

eg:class Person {
  protected name: string;
  constructor (name: string) {
    this.name = name;
  }
}
class Employ extends Person {
  private department: string;
  constructor(name: string, department: string) {
    super(name)
    this.department = department;
  }
  public getMesage() {
    return `hello, my name is ${this.name} 住在${this.department}`
  }
}
let em = new Employ('an', 'beijing')
console.log(em.getMesage());
console.log(em.name); // 报错,不能再person类以外使用name属性,但是可以在Employ中使用,因为Employ是Person派生
复制代码
  1. 抽象类 抽象类作为其他派生类的基类,一般不会直接被实例化。abstract关键字用于定义抽象类和在抽象类内部定义抽象方法。
abstract class Department {
  constructor(public name: string) { };
    printName(): void {
      console.log(`aaa${this.name}`)
    };
    abstract printMeeting(): void; // 必须在派生类中实现
}
class AccountDeparment extends Department {
  printMeeting(): void {
    console.log('111')
  }
  generator(): void {
    console.log('222')
  }
}
let department: Department; // 允许创建一个对抽象类型的引用
// department = new Department(); // 报错,不能创建一个抽象类的实例
department = new AccountDeparment('an'); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
// department.generator(); // 报错,类型Department上不存在generator
复制代码
  1. 高级技巧
class Greeter {
  static standardGreeting = 'hello there';
  greeting: string;
  greet() {
    if (this.greeting) {
      return `hello ${this.greeting}`
    } else {
      return Greeter.standardGreeting
    }
  }
}
let greet1 : Greeter;
greet1 = new Greeter();
console.log(greet1.greet());
/**创建一个greeterMaker变量,保存了这个类或者说保存了类构造函数。使用typeof Greeter意思是取Greeter类的类型而不是实例的类型。
确切的说就是‘告诉Greeter标识符的类型,也就是构造函数的类型,这个类型包含了类的所有静态成员和构造函数。’然后在greeterMaker上使用new,创建Greeter的实例
 *  */ 
let greeterMaker: typeof Greeter = Greeter;
greeterMaker.standardGreeting = 'hello';
let greet2: Greeter = new greeterMaker();
console.log(greet2.greet());
复制代码

函数

  1. 可选参数 ts中每个参数都是必须的,多传少传都会报错,当想实现可选参数的时候,在参数名旁边使用?实现可选参数的功能。但是可选参数必须放在必须参数的后面
function add(par1: string, par2: string) {
  return `${par1}${par2}`
}
// let result1 = add('猫'); 报错 少一个参数
// let result2 = add('猫', '狗', '鱼'); 报错,多一个参数
let result3 = add('猫', '狗');
function add2(par1: string, par2?: string) {
  return `${par1}${par2}`
}
// let result1 = add('猫'); 不报错
// let result2 = add('猫', '狗', '鱼'); 报错,应该有1-2个参数,但是出现了3个
let result3 = add('猫', '狗');
复制代码
  1. 默认参数 在所有必须参数后面的带默认初始化的参数都是可选的,与可选参数一样,在调用函数时候可以省略 带默认值的参数不用必须放在必须参数的后面,如果带默认值的参数要出现在必须参数前面时候,必须明确的传入undefined值。
function person(name: string, age = 18){
  return `名字是${name},年龄是${age}岁`
}
let re = person('an');
let re2 = person('an', undefined); // age为18
// let re3 = person('an', 20, 'anm'); //报错
let re4 = person('am', 22);
console.log(re,re2, re4);
复制代码
  1. 剩余参数 定义:不知道有多少个参数将要传进来,可能0个可能多个,把所有参数收集到一个变量里 编辑器创建参数数组,名字是你在...后面定的名字,可以在函数体内使用这个数组。
 function person (name: string, ...params: string[]) {
   return params;
 }
 let re = person('an', '18', 'amy');
 console.log(re, 're是') // ['18','amy']
复制代码
  1. this
  2. 重载

泛型

使用any类型可以接收任何类型的arg参数,传入的类型与返回的类型应该是相同的,但是用了any,我们传入一个数字,任何类型的值都有可能被返回

function identity(arg: any): any {
   return arg;
 }
复制代码

类型变量T:一种特殊的变量,只用于表示类型而不是值,使得返回值的类型与传入的参数的类型是相同的

  1. 泛型函数,适用于多个类型,不会丢失信息,传入数值类型并且返回数值类型
function identity<T>(arg: T): T {
 return arg;
}

// 第一种方法明确指定了T的类型,
let outPut = identity<string>('eww');
// 第二种方法,类型推论
let output2 = identity('90');
function a<T>(arg: T) : T {
 console.log(arg.length); // 报错,类型T上不存在属性length,因为传入的可能是number
 return arg;
}
// 泛型函数b,接收类型参数T和参数arg,它是个元素类型是T的数组,并返回元素类似是T的数组
function b<T>(arg: T[]) : T[] {
 console.log(arg.length); // 不报错
 return arg;
}
复制代码
  1. 泛型接口
interface Generic {
 <T>(arg: T) : T;
}
function identity<U>(arg: U): U {
 return arg;
}
let aa: Generic = identity;
复制代码
  1. 泛型类,使用<>括起泛型类型,跟在类名后面。指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型
 class Person<T> {
   zeroValue: T;
   add: (x: T, y: T) => T
 };
 let person = new Person<number>();
 person.zeroValue = 1;
 let a = person.add = function(x,y) {
   return x + y;
 }
复制代码
  1. 泛型约束 定义一个接口来描述约束条件,使用这个接口和extends关键字来实行约束
interface len {
  length: number
}
function logging<T extends len>(arg: T) : T {
  console.log(arg.length);
  return arg;
}
// logging(333); //报错,类型‘333’的参数不能赋给类型‘len’的参数;
logging('123');
复制代码

枚举

  1. 枚举通过关键字enum来定义,使用枚举可以定义一些有名字的数字常量,一个枚举类型可以包含零个或者多个枚举成员. 没有初始化函数并且之前的枚举成员是常数,在这种情况下,当前枚举成员的值为上一个成员的值加1,但是第一个如果没有初始化方法那它的初始值为0
enum Enum{
  A
}
let a = Enum.A;
let b = Enum[a];
console.log(a,b) // a是0,b是‘A’
复制代码
  1. 常数枚举 :在enum关键字前使用const修饰符,只能使用常数枚举表达式
const enum Par {
  A = 1,
  B = A*2
}
复制代码
  1. 外部枚举:描述已经存在的枚举类型的形状,避免重复的问题
declare enum Enum {
  A = 1, // 标识符重复
  B = A * 2,
}
复制代码

高级类型

Symbols

  1. symbol类型的值是通过Symbol构造函数创建,而且是不可改变的惟一的,可以被用作对象属性的键

模块

模块是自声明的,两个模块之间的关系是通过在文件级别上使用imports和exports建立的。

  1. 导出声明 任何声明,比如变量,函数,类,类型别名或接口都能够添加export关键字来导出。
  2. 导出语句 可能需要对导出的部分重命名 eg:export { ZipCode }; export { ZipCode as main };
  3. 重新导出 重新导出功能并不会在当前模块导入那个模块或者定义一个新的局部变量 或者一个模块可以包裹多个模块,并把他们导出的内容联合在一起通过语法: export * from 'module'
  4. 导入 导入内容重新命名: import { a as b } from ''
  5. 将整个模块导入到一个变量,通过它来访问模块的导出部分
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
复制代码
  1. 默认导出

默认导出使用default关键字标记,一个模块只能有一个default导出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值