TypeScript语法进阶重温系列(三)

162 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

1. TypeScript中的配置文件

  • 执行命令tsc则会按tsconfig中的配置来编译,如果是tsc xxx.ts则不会按tsconfig中的配置来编译【执行ts-node xxx.ts会按tsconfig中的配置来编译】

  • tsconfig.json中的配置项

    • include/files:需要编译哪些
    • exclude:哪些不需要编译
    • compilerOptions中的编译配置项
      • removeComments:是否去掉注释
      • noImplicitAny:是否要求指定any(属性值为true的时候必须加any)
      • strictNullChecks:是否强制检测null的类型
      • rootDir:编译后生成文件的存放目录
      • outDir:需要编译的文件目录
      • incremental:是否开启增量式的编译(即只编译修改的那部分代码)
      • target:编译后的代码版本
      • allowJs:是否允许js文件也能在ts编译时进行编译转换到指定的es版本
      • checkJs:是否允许对js代码进行语法检测(如同ts语法检测一样)
      • sourceMap:是否生成xxx.map文件
      • noUnusedLocals:是否开启对定义但未被使用的变量进行检测
      • noUnusedParameters:是否开启对声明但未被使用的函数参数进行检测

具体用法参考官网:www.typescriptlang.org/docs/handbo…

2. 联合类型和类型保护

联合类型

  • 联合类型采用|符号来连接不同的类型

  • 联合类型的代码提示只会提示共有的变量和方法,其他的不会提示也不能使用。若要使用,可以采取类型保护的方法。

类型保护的四种方法

  • 类型断言的方式
  • 使用in 语法来做类型保护
  • 使用typeof 语法来做类型保护
  • 使用instanceof 语法来做类型保护
interface Bird {
  fly: boolean;
  sing: () => {};
}

interface Dog {
  fly: boolean;
  bark: () => {};
}

// 类型断言的方式
function trainAnial(animal: Bird | Dog) {
  if(animal.fly) {
    (animal as Bird).sing()
  }else {
    (animal as Dog).bark()
  }
}

// 使用in 语法来做类型保护
function trainAnialSecond(animal: Bird | Dog) {
  if('sing' in animal) {
    animal.sing()
  }else {
    animal.bark()
  }
}

// 使用typeof 语法来做类型保护
function add(first: string | number, second: string | number) {
  if(typeof first === 'string' || typeof second === 'string') {
    return `${first}${second}`
  }
  return first + second
}

// 使用instanceof 语法来做类型保护
class NumberObj {
  count: number
}

function addSecond(first: object | NumberObj, second: object | NumberObj) {
  if(first instanceof NumberObj && second instanceof NumberObj) {
    return first.count + second.count
  }
  return 0
}

3. Enum 枚举类型

枚举类型一般用来做多个状态的条件判断,来使得代码的可读性增强

enum Status {
  OFFLINE,
  ONLINE,
  DELETED
}

console.log(Status.OFFLINE, Status[0]);  // 输出0 OFFLINE

// const Status = {
//   OFFLINE: 0,
//   ONLINE: 1,
//   DELETED: 2
// }

// function getResult(status) {
//   if (status === Status.OFFLINE) {
//     return 'offline';
//   } else if (status === Status.ONLINE) {
//     return 'online';
//   } else if (status === Status.DELETED) {
//     return 'deleted';
//   }
//   return 'error';
// }

// const result = getResult(1);
// console.log(result);

默认值从0开始,也可以修改,如下

enum Status {
  OFFLINE = 1,
  ONLINE,
  DELETED
}

console.log(Status.OFFLINE, Status[0]);// 输出为1 undefined(此时的Status[1]才是OFFLINE)

4. 函数泛型

泛型即泛指的类型

  • 泛型声明:函数名后面用<xx>进行声明,然后参数和返回值都可以使用xx类型进行类型定义
  • 泛型使用:函数调用时在函数名后面用面用<具体类型>显式声明类型 或者 使用ts的类型推断机制
// 泛型 generic 
function join<T, P>(first: T, second: P) {
  return `${first}${second}`;
}

function anotherJoin<T>(first: T, second: T): T {
  return first;
}

// T[]
function map<T>(params: Array<T>) {
  return params;
}

// join<number, string>(1, '1');
// map<string>(['123']);
join(1, '1'); // 也不会报错,因为ts会进行类型推断

5. 类中的泛型以及泛型类型

  • 如果类中需要约束泛型必须有某个属性,如name: string,则可以用泛型来继承定义好的接口,如<T extends Item>
  • 如果类中需要约束泛型只能为特定类型,可以使用extends来继承类型。如<T extends number | string>该泛型表示必须拥有number或者string类型的相关属性。
// interface Item {
//   name: string;
// }

// class DataManager<T extends number | string> {
//   constructor(private data: T[]) {}
//   getItem(index: number): T {
//     return this.data[index];
//   }
// }

// const data = new DataManager<number>([1]);
// data.getItem(0);

// const data = new DataManager([
//   {
//     name: 'dell'
//   }
// ]);

// interface Test {
//   name: string;
// }

// const data = new DataManager<number>([]); // 此时的泛型使用必须为number或者string或者拥有其中一种类型的所有相关属性,不能为Test

// 如何使用泛型作为一个具体的类型注解
function hello<T>(params: T) {
  return params;
}

const func: <T>(param: T) => T = hello;

下一篇:TypeScript语法进阶重温系列(四)