Typesctipt基础(二)

简介: Typesctipt基础(二)

Typescript 类型

Object 类型

Object 类型不单指对象,还有数组、函数。

const foo: object = function () {}; // 也可以是{} || []
const obj: {} = {}; // 只能是对象
复制代码

数组类型

const arr1: Array<number> = [1, 2, 3];
const arr2: number[] = [1, 2, 3];
function sum(...args: number[]){
    return args.reduce(prev,current) => prev+current, 0)
}
复制代码

元组类型

元组类型是一种特殊的数据结构,元组就是一个明确元素数量以及每个元素类型的数组,各个元素的类型可以不相同。比如在 React 中的 useState 返回的就是一个元组类型。

const tuple: [number, string] = [18, "123"];
复制代码

枚举类型

enum Status {
    Draft = 2,  // 这里指定了从2开始累加,表示后面的Unpublished与Published分别是3、4;如果设置的是字符串类型,则无法自增
    Unpublished,
    Published
}
const post = {
  tag: 2, // 1 || 3, 不用枚举类型,用字面量形式
  status: Status.Draft
};
复制代码

编译之后会发现一个双向键值对的对象,双向键值对可以通过键获取到值,也可以通过值获取到键。这样可以动态的根据枚举值去获取枚举的名称。

网络异常,图片无法展示
|

函数类型

在 Javascript 中有函数定义方式:函数声明和函数表达式。这两种方式如何进行类型约束:

// 函数声明
function fun1(a: number): string {
  return "fun1";
}
// 函数表达式
const fun2 = function (a: number): string {
  return "fun2";
};
复制代码

任意类型

由于 Javascript 是弱类型的关系,很多内置 API 本身接收任意类型的参数。Typescript 提供了 any 这种类型,其不会进行类型检查。

let foo: any = "string";
复制代码

隐式类型推断

在 Typescript 中,如果没有明确通过类型注解去标记变量的类型,Typescript 就会根据变量的使用情况去推断便来那个类型,这个行为就叫做隐式类型推断。如果 Typescript 无法判断出类型就会标记为 any。

let foo = 1;
foo = "123"; // 报错
let foo2; // 判定为any
foo2 = 123;
foo2 = "123";
复制代码

类型断言

在某些情况下,Typescript 无法判断出变量的类型,而作为开发者,可以根据变量使用情况推断出类型。

类型断言可以告诉 Typescript 变量的类型是什么,但它并不是类型转换。类型断言是属于编译阶段的概念,而类型转换属于代码执行阶段的概念。

const nums = [1, 2, 3];
const res = nums.find((i) => i > 0); // 这里明显会返回一个number,但是typescript却推断出是一个number或undefined。这时就可以进行 as关键词 或<number>断言,告诉typescript res是一个number
const num1 = res as number;
const num2 = <number>res; // 不过当在代码中使用jsx时,这种方法会与jsx语法产生冲突
复制代码

Typescript 接口 interface

interface 可以理解为一种规范或契约。接口用来约束对象的结构。接口可以设定可选、只读成员

interface IPost {
  title: string;
  subTitle?: string; // 可选
  readonly summary: string; // 只读
  [Math.random()]: "2"; // 动态
}
function printPost(post) {
  console.log(post.title);
}
复制代码

Typescript 的类

类的基本使用

类的作用:描述一类具体事物的抽象特征,从代码程度上来说,用来描述一类具体对象的抽象成员。 在 ES6 以前,Javascript 都是通过函数+原型模拟实现类。ES6 开始 Javascript 中有了专门的 class,而 Typescript 中则增强了 class 的相关语法。

Typescript 相对于 ECMAScript 新增了哪些内容:

  • 1.类的属性在使用之前必须类型声明
class Person {
  name: string;
  constructor(name: string, age: number) {
    this.name = name; // 未报错
    this.age = age; // 报错类型“Person”上不存在属性“age”。
  }
}
复制代码

类的访问修饰符

定义成员可访问的级别

访问修饰符 描述
private 私有属性,只能在类的内部访问
public 默认值,公有属性
protected 在外部不能访问,跟 private 区别在于,protected 可以被子类访问

而对于构造函数 constructor 的访问修饰符,默认也是 public,如果设置成了 private,那么这个类型不能被外部实例化,也不能被继承,这样只能在类的内部添加一个静态方法,在这个静态方法中创建实例;如果设置成了 protected,也不能被外部实例化,但是可以被继承。

class Person {
  name: string;
  private constructor(name: string) {
    this.name = name;
  }
}
const jack = new Person(); // 报错:类“Person”的构造函数是私有的,仅可在类声明中访问。
复制代码
class Person {
  name: string;
  private constructor(name: string) {
    this.name = name;
  }
  static create(name: string) {
    return new Person(name);
  }
}
const jack = Person.create("jack");
复制代码

类的只读属性

如果有访问修饰符,则只读属性放在修饰符后面

class Person {
  private readonly name: string;
  constructor(name: string) {
    this.name = name;
  }
}
复制代码

类与接口

interface EatAndRun {
  eat(food: string): void;
  run(distance: number): void;
}
class Person implements EatAndRun {
  eat(food: string): void {
    console.log("eat");
  }
  run(distance: number) {
    console.log("run");
  }
}
class Animal implements EatAndRun {
  eat(food: string): void {
    console.log("eat1");
  }
  run(distance: number) {
    console.log("run1");
  }
}
复制代码

注意,实际开发中,一般是一个接口约束一个能力,一个类型实现多个接口,低耦合原则:

interface Eat {
  eat(food: string): void;
}
interface Run {
  run(distance: number): void;
}
class Person implements Eat, Run {
  eat(food: string): void {
    console.log("eat");
  }
  run(distance: number) {
    console.log("run");
  }
}
class Animal implements Eat, Run {
  eat(food: string): void {
    console.log("eat1");
  }
  run(distance: number) {
    console.log("run1");
  }
}
复制代码

抽象类

抽象类不同于接口的是:抽象类可以包含一些具体的实现。

定义抽象类的方式:在 class 关键词之前添加 abstract。抽象类只能被继承,不能通过 new 创建实例对象。抽象类里可以定义抽象方法,抽象方法不需要方法体,当父类有这个抽象方法,子类就需要实现这个方法。

export {};
abstract class Animal {
  // 抽象类
  eat(food: string): void {
    console.log("eat1");
  }
  abstract run(distance: number): void; // 抽象方法
}
class Dog extends Animal {
  run(distance: number): void {
    // 子类修正父类的抽象方法
    console.log("run");
  }
}
const d = new Dog();
复制代码

泛型

泛型:声明时不指定具体的类型,使用时再指定。目的是极大程度的复用代码。

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;
}
// 使用泛型,不明确类型的地方使用T
function createArray<T>(length: number, value: T): T[] {
  const arr = Array<T>(length).fill(value);
  return arr;
}
const res = createArray<string>(3, "foo");
复制代码

类型声明

在开发过程中难免会用到 npm 的第三方模块,这些模块不一定都是通过 Typescript 编写的,因此其提供的成员不会有强类型的体验。比如 lodash,就需要安装类型说明模块 types/lodash。如果没有对应的声明模块,可以通过 declare 语句自定义声明。

import { camelCase } from 'lodash';
declare function camelCase(input: string): string
const res = camelCase('hello typed')
复制代码

安装了 lodash,但是没有安装类型声明文件 types/lodash,因此在代码中会报错:

网络异常,图片无法展示
|


相关链接

TypeScript 入门教程

相关文章
基础练习-2
基础练习-2
84 0
|
2月前
|
编译器 Linux C语言
C++基础篇(1)
C++基础篇(1)
64 0
|
7月前
|
传感器 编解码 C++
C++视频基础
C++视频基础
|
数据安全/隐私保护
基础练习-6
基础练习-6
79 0
|
XML 数据可视化 Android开发
Android程序设计基础
Android程序设计基础
144 0
Android程序设计基础
|
自然语言处理 JavaScript 前端开发
Typesctipt基础(一)
Typesctipt基础(一)
168 0
|
机器学习/深度学习 人工智能 算法
|
存储 C#
C#基础
C#基础
98 0
|
开发框架 安全 .NET
C#基础04
C#基础04
129 0
C#基础04
|
存储 C#
C#基础03
C#基础03
136 0
C#基础03