TypeScript疑难解析

2020-05-18  本文已影响0人  zxhnext

1. 语言类型

1.1 强类型与弱类型

强类型不允许随意的隐式类型转换,而弱类型是允许的
强类型和弱类型区别是是否允许随意的隐式转换
强类型是语法层面限制类型,如果类型不对,编译阶段就会报错。而js只能在运行阶段通过类型判断去限制。这也就意味着JS只能到代码运行到这一行时才能发现错误,不能像其它语言编译阶段就可以发现错误

强类型优势:

  1. 更早发现错误(编译阶段就可发现错误,不用等到代码运行)
  2. 代码更智能,编码更准确
  3. 重构更牢靠
  4. 减少不必要的类型判断

1.2 静态类型与动态类型

静态类型:一个变量声明时它的类型就是明确的,声明过后,它的类型就不允许再修改
动态类型:运行阶段才能够明确变量类型,而且变量类型随时可变
静态类型与动态类型区别是是否允许随时修改变量类型


image.png

JS是弱类型,动态类型

2. TS简介

下面这张图可以让我们充分的理解什么是TS


image.png

3. TS环境配置

3.1 生成ts配置文件

tsc --init

3.2 将报错信息设置为中文

tsc --locale zh-CN

vs code中在设置里搜索typescript locale,改为中文即可

4. ts的几种数据类型

const a: string = "foobar";
const b: number = 100; // NaN Infinity
const c: boolean = true;
// const d: boolean = null;
const e: void = undefined; // 非严格模式下也可以赋值null, 严格模式下只能赋值undefined
const f: null = null;
const g: undefined = undefined;
const h: symbol = Symbol(); // es5中不能使用Symbol(),包括es6中的Promise等, 解决办法,在配置文件中添加"lib": ["es2015", "DOM"], DOM是默认的的,不开启lib时默认就有

5. 定义类型

5.1 object

ts中的object包括{}, [], function

const foo: object = {} // [] // function() {}

但是如果仅仅想声明对象,需要使用对象字面量语法

const obj: {} = {};

5.2 array

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

5.3 元组

元组是明确元素数量与元素类型的数组
常见用于函数返回值

5.4 枚举

常见用于用某几个数值代表某种状态

let state = 0; // 0, 1, 2三种状态

enum PostStatus {
  Draft, // = 0
  UnPublished, // = 1
  Published, // = 2
}

// 编译后
(function (PostStatus) {
    PostStatus[PostStatus["Draft"] = 0] = "Draft";
    PostStatus[PostStatus["UnPublished"] = 1] = "UnPublished";
    PostStatus[PostStatus["Published"] = 2] = "Published";
})(PostStatus || (PostStatus = {}));

如果是字符串枚举,因为无法自增,所以就必须给每一个成员手动添加值

enum PostStatus {
  Draft = 'aaa'
  UnPublished = 'bbb'
  Published = 'ccc'
}

枚举会侵入代码,建议使用常量枚举,即在枚举前加const

const enum PostStatus {
  Draft, // = 0
  UnPublished, // = 1
  Published, // = 2
}

5.5 函数

  1. 函数声明
    行参和实参数量必须相等
function func1(a: number, b: number): string { 
    return 'str'
}
func1(100, 200)
  1. 可选参数
function func2(a: number, b?: number): string {
  return "str";
}
// 或者使用默认参数
function func3(a: number, b: number = 10): string {
  return "str";
}
  1. 传入多个参数
function func4(a: number, b: number, ...rest: number[]): string {
  return "str";
}
  1. 函数表达式
const func5: (a: number, b: number, ...rest: number[]) => string = function (
  a: number,
  b: number
): string {
  return "str";
};

6. any(任意参数)

6.1 隐式类型推断

let age = 10; // 隐式推断为number类型
age = "str"; // 赋值string类型时报错

let foo; // 声明并未赋值,此时推断为any类型,下面先赋值number,再赋值string,也不会报错
bar = 10; // any
bar = "str"; // any 

6.2 类型断言

类型断言有as或者<><>在jxs语法中会和标签产生冲突,所以推荐使用as

const nums = [100, 200, 300, 400];
const res = nums.find((i) => i > 0);

const num1 = res as number;
const num2 = <number>res;

7. 接口

7.1 只读 readonly

7.2 动态属性

如果不确定有几个值,可以用以下方法

interface cache {
  [key: string]: string
}

8. 类

最新的语法中,不再在construction通过this来动态添加属性,而是在外面对每个属性声明

// 如果没有在外部设置属性值,那就要在construction中设置属性值
class Person {
  name: string = "init name"
  age: number
  constructor(name: string, age: number) {
    this.name = name // 不再直接通过this来动态添加属性,而是需要在外面声明
    this.age = age
  }
}

8.1 修饰符

public
private
protected(可以在子类获取,外部获取不到)

注意:如果给constructor设置了private,那么外部就不能实例化了,但是内部可以访问到,所以这是我们在内部加一个静态方法,去返回实例

class Student extends Person {
  private constructor(name: string, age: number) {
    super(name, age)
    console.log(this.gender)
  }
  static create(name: string, age: number) {
    return new Student(name, age)
  }
}

const jack = Student.create("jack", 18)
console.log(jack.name)
console.log(jack.age)
console.log(jack.gender)

8.2 只读属性readonly

8.3 类与接口

接口仅定义公共能力,而不做具体方法实现,建议一个接口只实现一个功能

interface Eat {
  eat(food: string): void
}

interface Run {
  run(distance: number): void
}

class Person implements Eat, Run {
  eat(food: string): void {
    console.log(`优雅的进餐,${food}`)
  }
  run(distance: number): void {
    console.log(`直立行走:${distance}`)
  }
}

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

8.4 抽象类

与接口类似,如果比较复杂的类建议使用抽象类
注意:抽象类无法new,只能继承

abstract class Animal {
  eat(food: string): void {
    console.log(`呼噜呼噜的吃,${food}`)
  }
  abstract run(distance: number): void
}

class Dog extends Animal {
  run(distance: number): void {
    console.log(`爬行:${distance}`)
  }
}

9. 泛型

function createNumberArray(length: number, value: number): number[] {
  const arr = Array<number>(length).fill(value)
  return arr
}

function createStringArray(length: number, value: string): string[] {
  const arr = Array<string>(length).fill(value)
  return arr
}

function createArray<T>(length: number, value: T): T[] {
  const arr = Array<T>(length).fill(value)
  return arr
}

const resResult = createArray<string>(3, "foo")

10. 类型声明

如果一个成员在定义时没有声明类型,那么在使用时可以为他声明类型

import { camelCase } from 'lodash'
declare function camelCase(input: string): string
const res = camelCase('hello typed')

一般第三方库都有单独的类型声明模块,例如lodash的声明模块@types/lodash

上一篇 下一篇

猜你喜欢

热点阅读