typescript入门级教程

82 阅读3分钟

数据类型

最新的ECMAScript标准定义了8种数据类型 7种原始类型:

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol
  • BigInt 和Object类型;

原始类型:

// basic types
let isDone: boolean = false;
let age: number = 10;
let firstName: string = "mj";

let u: undefined = undefined;
let n: null = null;

// 未知类型
let noSure: any = 4;
noSure = "maybe a string";
noSure = true;

noSure.myName;
noSure.getName();

object类型:

// object类型
// Array
let arrOfNumbers: number[] = [1, 2, 3, 4];
arrOfNumbers.push(3);

// tuple
let user: [string, number] = ["mj", 22];

// function
function add(x: number, y: number): number {
  return x + y;
}
let result = add(2, 3);
// 函数表达式
const add2 = (x: number, y: number): number => {
  return x + y;
};
// type inference 类型推论
const add3 = add2;

接口Interfaces

1.对对象的shape进行描述:

interface Person {
  readonly id: number;
  name: string;
  age?: number;
}

let mj: Person = {
  id: 1,
  name: "mj",
};

2.函数类型:

const sum = (x: number, y: number) => {
  return x + y;
};
interface ISum {
  (x: number, y: number): number;
}
const sum2: ISum = sum;

3.还能约束变化的属性名称,有可能有多个不确定的属性:

// 可索引的类型
interface RandomMap {
  [propName: string]: string;
}
const test: RandomMap = {
  a: "test1",
  b: "test2",
};
// 类数组的结构
interface likeArray {
  [propName: number]: string;
}
const arr: likeArray = ["1", "2", "3"];

4.定制化

// 类似于Reactde FunctionComponent
interface FunctionWithProps {
  (x: number): number;
  name: string;
}
const a: FunctionWithProps = (x: number) => {
  return x;
};
a.name = "1";

IMG_1228.png

类和接口

1.类的基本定义

// 类的基本定义
class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  run() {
    return `${this.name} is running`;
  }
}
const dog = new Animal("pipi");
dog.run();

2.继承

// 继承
class cat extends Animal {
  miao() {
    return `${this.name} is miaomiao~`;
  }
}
const xiongmao = new cat("xiongmao");
xiongmao.miao();

3.多态

//多态
class Mouse extends Animal {
  constructor(name) {
    super(name);
    console.log(this.name);
  }
  run() {
    return "shushu" + super.run();
  }
}
const shushu = new Mouse("shushu");

ts如何增强类呢?

  • public 公有,任何地方可以访问,默认都是public;
  • private 私有,不能在它声明之外的地方访问;
  • protected 子类中允许访问;

约束implements:

interface ClockInterface {
  currentTime: number;
  alert(): void;
}
interface GameInterface {
  play(): void;
}

class Clock implements ClockInterface {
  currentTime: number = 1;
  alert(): void {}
}

class Cellpnone implements ClockInterface, GameInterface {
  currentTime: number = 1;
  alert(): void {}
  play() {}
}

Clock implements一个interface只是约束了实例类型,对于静态类型需要创建另外一个interface来约束;

interface ClockInterface {
  currentTime: number;
  alert(): void;
}

// 静态类型
interface ClockStatic {
  new (h: number, m: number): void;
  time: number;
}

const Clock: ClockStatic = class Clock implements ClockInterface {
  constructor(h: number, n: number) {}
  static time;
  currentTime: number = 1;
  alert(): void {}
};

泛型Generics

函数没有类型推断; 如果有了泛型, 根据传参的类型,推断出返回数据的类型:

image.png

image.png

function swap<T, U>(tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]];
}
const res = swap(["string", 123]);

interface GithubResp {
  name: string;
  count: number;
}

interface CountryResp {
  name: string;
  area: number;
  population: number;
}

function withAPI<T>(url: string): Promise<T> {
  return fecth(url).then((resp) => resp.json());
}

withAPI<GithubResp>("github.user").then((resp) => {});

withAPI<CountryResp>("github.user").then((resp) => {});

泛型和接口举例

这里是仿写React的FunctionComponent;

interface FunctionComponent<P = {}> {
  (props: P, context?: any): any;
}

interface TestProps {
  title: string;
  desc: string;
}
// 是将TestProps传递到函数的参数
const test: FunctionComponent<TestProps> = (props) => {
  return `${props.title} ${props.desc}`;
};

深入泛型

1.交叉类型和联合类型

// 交叉类型
interface IName {
  name: string;
}

type IPerson = IName & { age: number };
let person: IPerson = {
  name: "hello",
  age: 30,
};

// 联合类型
let numberOrString: number | string;
  1. 类型断言
// 类型断言
function getLength(input: number | string) {
  const str = input as string;
  if (str.length) {
    return str.length;
  } else {
    const number = input as number;
    return number.toString().length;
  }
}

3.Partial用法;

// Partial用法
interface Person {
  name: string;
  age: number;
}

type PersonOptional = Partial<IPerson>;
// name和age属性都是可选的
let mj: PersonOptional = {};
type Partial<T> = {
   [P in keyof T]?: T[P];
};

高级特性

  1. keyof

image.png

2.只能在Keys中选

interface CountryResp {
  name: string;
  area: number;
  population: number;
}

type Keys = keyof CountryResp;
type NameType = CountryResp["name"];

// 只能在Keys中选
let key: Keys = "area";
  1. mapped keys image.png

属性变为可选(类似于Partial的写法); image.png

extends

// extends in generics

interface IwithLength {
  length: number;
}

// 对函数进行约束,只能传入有length属性的变量;
function echoWithArr<T extends IwithLength>(arg: T): T {
  console.log(arg.length);
  return arg;
}

const arr = echoWithArr([1, 2, 3]);
const str = echoWithArr("111")
const obj = echoWithArr({length: 1})
// T的类型不是null或undefined就返回T
type NonType<T> = T extends null | undefined ? never : T;
//demo1是number
let demo1: NonType<number>;
//demo2是string
let demo2: NonType<string>;

image.png

image.png

定义文件

// 定义了jQuery的类型
declare var jQuery: (selector: string) => any;

可以直接安装第三方的声明文件npm包;

myFetch<string>("test", "DELETE", { name: "hello" }).then((data) => {
  console.log(data);
});
myFetch.get<number>("test").then((data) => {});
type HTTPMethod = "GET" | "POST" | "PATCH" | "DELETE";

declare function myFetch<T = any>(
  url: string,
  method: HTTPMethod,
  data?: any
): Promise<T>;

declare namespace myFetch {
  const get: <T = any>(url: string) => Promise<T>;
  const post: <T = any>(url: string) => Promise<T>;
}