TypeScript学习

245 阅读5分钟
  • 强类型与弱类型
  • 静态类型和动态类型
  • javaScript 自有类型系统的问题
  • Flow静态类型检查方案
  • TypeScript语言规范与基本应用。

类型系统

  1. 强类型与弱类型 (类型安全)
  2. 静态类型和动态类型 (类型检查) 强类型语言中不允许任意的隐式类型转换, 弱类型语言则允许任意 的数据隐式类型转换。

使用 flow

  1. 安装flow yarn add flow-bin --dev 变量加:【所需要的类型】
  2. 代码前@flow.
  3. yarn flow 移除flow注释。 安装: yarn add flow-remove-types --dev 删除 yarn flow-remove-types . -d dist生成新的文件 使用babel 首先安装: @babel/cli // 核心模块 @babel/core // 核心模块 @babel/preset-flow // 移除flow注释

类型注释

/**
* 类型注释
* @flow
* 
*/
function square (n: number) {
    return n * n
}
let num: number = 100

function foo():number {
    return 100
}
function f00(): void{
    // 没有返回值。
}

原始类型

const a: string = 'foobar' const b: number = // NaN // 100 const c: boolean = false const d: null = null const e: void = undefined const f: symbol = Symbol()

数组类型

const arr1: Array // 全部由数字组成的数组。 const arr2: number[] = [1,2,33] // 全部由数字组成的数组。 const foo: [string, number] = ['foo', 100] // 元组 固定类型和长度

对象类型

const obj1: {foo: string, bar: number} = {foo; 'string', bar: 100} // 元组 固定类型
const obj2: {foo?: string, bar: number} = {bar: 100} // ? 代表不是必须 的。
const obj3: {[string]: string} = {} // 健和值都是字符串。
obj3.key1 = 'value'
obj3.key2 = '100'

函数类型

function foo (callback: (string, number) => void) {
    callback('string', 100)
}

特殊类型

const a: 'foo' = 'foo'; // 指定自定义类型
const type: 'success' | 'warning' | 'danger' = 'warning'; // 指定指定值
type StringOrNumber = string | number // 变量声明
const foo: StringOrNumber = 'as' || 112; // 只能是这几个
const gender: ? number = null; // number || null || undefined 

Miixed ant Any

function passMinxed (value: mixed) {

}
passMinxed('string') // : mixed 任意类型的数据 强类型
passMinxed(100)

function passAny (value: any) {

}
passAny('string') // : any 任意类型的数据 弱类型
passAny(100)

flow 小结

www.saltycrane.com/cheat-sheet…

TypeSript 基本使用。

类型使用跟flow一样。 可以跟babel一样可以将es6+, 降低到es3左右版本。可以在任何js运行环境运行。 编译指定文件

yarn add typescript --dev
yarn tsc test.ts
// 就会生成test.js

ts 工程化文件

yarn tsc --init 生成tsconfig.json 打开tsconfig.json

compilerOptions :{
    "target": "es2015",    // 编译到es2015
    "module": "commonjs",   //文件输出和引入使用commonjs
    "sourceMap": true,   // 输出sourceMap
    "outDir": "dist",    // 编译完输出到这个文件夹
    "rootDir": "src",   // 把哪个文件编译成js.
    "strict": true,     // 严格模式开启所以文件的严格模式。 变量为null会报错
    "strictNullChecks": true,  // 只检查变量不能为空的。
}
// 运行
yarn tsc 
// 会生成dist文件夹

void 类型

是为了函数没有返回值来定义的。也可以定义变量 在非严格模式下: void :类型可以是null or ubdefined 在严格模式下: void :类型只能是null

ts配置文件

// tsconfig.json 
"lib": ["ES2015","DOM"], // 引入ES2015 and DOM

使用中文的错误消息

yarn tsc --locale zh-CN 强制转换。

ts Object 类型

const foo:object = function () {}
const obj: {foo:number, bar:string} = {
    foo: 123,
    bar: 'string',
    more: 123 // 报错
}

数组类型

const arr1: Array<number> = [1, 2, 3, 3];
const arr2: number[] = [1, 3, 4, 5];

function sum(...args: number[]) {
  return args.reduce((prev, current) => prev + current);
}
sum(1,2,3,'ww'); // 报错

元组

const tuple: [number, string] = [18, 'sex']
const [age, sex] = tuple
console.log(age, sex);

枚举

使用const枚举编译完之后会删除调掉定义的枚举。 不使用则不会。编译完会生成一个双向健值对对象。 枚举不设置值会自动从零开始。依次加一。

const enum PostStatus {
  Draft = 0,
  Unpublished = 1,
  Published = 'ccc',
}
const post = {
  title: 'Hello TypeScript',
  content: 'scxkdcmkdm',
  status: PostStatus.Draft
}


// enum PostStatus {
//   Draft = 0,
//   Unpublished = 1,
//   Published = 'ccc',
// }
// const post = {
//   title: 'Hello TypeScript',
//   content: 'scxkdcmkdm',
//   status: PostStatus.Draft
// }

TS 函数类型

// 函数声明
// ?表示可选参数。没有问号说明就是两个参数。不可少,
// 如果参数添加默认值的话这个 参数也是可选状态的
// 可选参数必修放在必选参数之后。
function func1 (a: number, b?: number): string {
    return 'func1'
}
// 任意参数写法。
function func1 (...rest: number[]): string {
    return 'func1'
}

// 函数表达式
const fun2:(a:number, b: number) => string = function (a:number, b: number): string {
    return 'func2'
}

任意类型 any

function stringify (value: any) {
    return JSON.stringify(value)
}

变量在声明的时候我们将它赋值就算没有给她类型呢 。它也会根据相应的值推断出他的类型。

TS断言

const nums = [1,34,5,6];
const res = nums.find(i => i > 0);
const num1 = res as number;//  强制指定变量的类型。
// 还可以这么写
const num2 = <number>res // jsx--下会冲突。

ts接口

interface 关键词 设置某一个对象里面每个属性的类型。 readonly: 只读

interface Post {
  title: string,
  content: string,
  subtitle?: string // 可选成员
  readonly summary: string // 只读
}
const hello: Post = {
   title: '23',
   content: '23',
   summary: 'asdwdw' // 初始化之后不允许修改。
}

不知道这个对象有多少参数。

interface Cache {
  [prop: string]: string
}
const cache: Cache = {}

cache.foo = 'value1'
cache.bar = 'value2'

class Person {
  public name: string = 'init name' // 公共属性
  private age: number  // private 标记为私有属性。子类不可访问
  // readonly需要在访问修饰符后面。 类型声明的时候使用等号赋值。
  protected readonly gender: boolean // protected 受保护的属性 不允许外部访问 只允许子类访问
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  sayHi(msg: string): void {
    console.log(`I am ${this.name}, ${msg}`);
    console.log(this.age);
  }
}
class Student extends Person {
  private constructor(name: string, age: number) {
    super(name, age);
    console.log(this.gender);
  }
  static created(name: string, age: number) {
    return new Student(name, age); // 
  };
}
Student.created('小红', 18); // 使用它的静态方法来实现new一个新的对象。
const tom = new Person('tom', 18);
console.log(tom.name);
console.log(tom.age); // 属性“age”为私有属性,只能在类“Person”中访问。
console.log(tom.gender); // 属性“gender”受保护,只能在类“Person”及其子类中访问
const jack = new Student(); // 类“Student”的构造函数是私有的,仅可在类声明中访问

TS类与接口

interface EatAndRun {
  eat(food: string): void
  run(distance: number): void
}

class Person implements EatAndRun {
  eat(food: string): void {
    console.log(`优雅的进餐: ${food}`);
  }
  

}
class Animal implements EatAndRun {
  eat(food: string): void {
    console.log(`呼噜噜吃: ${food}`);
  }
  run(distance: number) {
    console.log(`爬行: ${distance}`);
  }
}
类“Person”错误实现接口“EatAndRun”。
  类型 "Person" 中缺少属性 "run",但类型 "EatAndRun" 中需要该属性。ts(2420)
test.ts(3, 3): 在此处声明了 "run"

接口需要细化一般一个接口只完成一个功能

interface Eat {
  eat(food: string): void
  run(distance: number): void
}
interface Run {
  eat(food: string): void
  run(distance: number): void
}

class Person implements Eat, Run {
  eat(food: string): void {
    console.log(`优雅的进餐: ${food}`);
  }
  

}
class Animal implements Eat, Run {
  eat(food: string): void {
    console.log(`呼噜噜吃: ${food}`);
  }
  run(distance: number) {
    console.log(`爬行: ${distance}`);
  }
}

抽象类。

abstract class Aniaml { // 抽象类只能被继承不能被实例出对象。
  eat(food:string):void {
    console.log(`呼噜噜吃:${food}`)
  }
  abstract run(distance: number):void
}
class Dog extends Aniaml {
  run(distance: number): void{
    console.log('四角爬行', distance)
  }
}
const d = new Dog();
d.eat('嗯洗吗')
d.run(12)

TS泛型

// function createNumberArray(length: number, value: number): number[] {
//   const arr = Array<number>(length).fill(value);
//   return arr;
// }
// const res = createNumberArray(12, 123);
// 将不确定的类型加上函数旁边加上<T>, 所以不确定的类型让T代表。
function createNumberArray<T>(length: number, value: T): T[] { 
  const arr = Array<T>(length).fill(value);
  return arr;
}
const res = createNumberArray(12, 123);