TypeScript

基础类型

  1. // 常见原始类型: string,number,boolean,undefined,null,symbol
  2. let var1: string; // 类型注解
  3. // 编译器类型推断可省略这个语法
  4. let var2 = true;
  5. // 类型数组
  6. let arr: string[];
  7. // 函数中的类型约束
  8. // 函数中的类型约束
  9. function greet(person: string): string {
  10. return 'hello, ' + person;
  11. }
  12. // void类型,常用于没有返回值的函数
  13. function warn(): void {}

类型断言

  1. let strLength: number = (<string>someValue).length;
  2. let strLength: number = (someValue as string).length;
  3. //上面两种都是类型断言写法

非空断言

  1. function addFeatur(e: KeyboardEvent) {
  2. const inp = e.taget as HTMLInputElement;
  3. const inp = e.taget!;
  4. }

类型别名

  1. // 可以用下面这样方式定义对象类型
  2. const objType: { foo: string; bar: string };
  3. // 使用type定义类型别名,使用更便捷,还能复用
  4. type Foobar = { foo: string; bar: string };

联合类型

  1. let features: Features[] | null;

交叉类型

  1. type First = { first: number };
  2. type Secord = { secord: string };
  3. type third = First & Secord;

为了分离类型,比如前端类型和后端返回的类型应该分开定义后合并

合起来,如果有同 key,类型不一样,怎么处理的?

重载

以函数参数数量或者类型,或者返回值的类型区分多个同名函数

  1. // 重载:以函数参数数量或者类型,或者返回值的类型区分多个同名函数
  2. // 先声明,再实现
  3. // 重载1
  4. function watch(cb1: () => void): void;
  5. // 重载2
  6. function watch(cb1: () => void, cb2: (v1: any, v2: any) => void): void;
  7. // 实现
  8. function watch(cb1: () => void, cb2?: (v1: any, v2: any) => void) {
  9. if (cb2) {
  10. console.log("执行重载2");
  11. } else {
  12. console.log("执行重载1");
  13. }
  14. }
  15. watch();

声明文件

  1. // shims-vue.d.ts
  2. import Vue from "vue";
  3. import { AxiosInstance } from "axios";
  4. declare module "vue/types/vue" {
  5. interface Vue {
  6. $axios: AxiosInstance;
  7. }
  8. }

Class

  1. // 03-class.ts
  2. class Parent {
  3. private _foo = "foo"; // 私有属性,不能在类的外部访问
  4. protected bar = "bar"; // 保护属性,可以在子类中访问
  5. // 参数属性:构造函数参数加修饰符,能够定义为成员属性
  6. constructor(public tua = "tua") {}
  7. // 方法也有修饰符
  8. private someMethod() {}
  9. // 存取器:属性方式访问,可添加额外逻辑,控制读写性
  10. get foo() {
  11. return this._foo;
  12. }
  13. set foo(val) {
  14. this._foo = val;
  15. }
  16. }

泛型

使用时机:

当你的函数,接口或者类:

  • 需要作用到很多类型的时候,
  • 需要被用到很多地方的时候,

泛型使用

可以作为一个动态参数传入,使类型使用更加灵活

  1. interface Result<T> {
  2. ok: 0 | 1;
  3. data: T[];
  4. }
  5. function getResult<T>(data: T): Result<T> {
  6. return { ok: 1, data: [data] };
  7. }
  8. getResult<string>("1");

keyof

keyof 操作符可以用来一个对象中的所有 key 值:

  1. interface Person {
  2. name: string;
  3. age: number;
  4. }
  5. type K1 = keyof Person; // "name" | "age"
  6. type K2 = keyof Person[]; // "length" | "toString" | "pop" | "push" | "concat" | "join"
  7. type K3 = keyof { [x: string]: Person }; // string | number

in

in 用来遍历枚举类型:

  1. type Keys = "a" | "b" | "c"
  2. type Obj = {
  3. [p in Keys]: any
  4. } // -> { a: any, b: any, c: any }

TS 泛型工具 (目前 16 种)

点击查看官方实现

功能是将类型的属性「变成可选」

  1. type Partial<T> = { [P in keyof T]?: T[P] };

功能是将类型的属性「变成只读」, 在属性前面增加 readonly 意思会将其变成只读。

  1. type Readonly<T> = { readonly [P in keyof T]: T[P] };

功能是用来得到一个函数的返回值类型。

  1. type ReturnType<T extends (...args: any[]) => any> = T extends (
  2. ...args: any[]
  3. ) => infer R
  4. ? R
  5. : any;

功能和Partial 相反,是将类型的属性「变成必填」, 这里的 -指的是去除。 -?意思就是去除可选,也就是必填啦。

  1. type Required<T> = { [P in keyof T]-?: T[P] };

TypeScript 装饰器

装饰器是什么

  • 它是一个表达式
  • 该表达式被执行后,返回一个函数
  • 函数的入参分别为 target、name 和 descriptor
  • 执行该函数后,可能返回 descriptor 对象,用于配置 target 对象

装饰器的分类

  • 类装饰器(Class decorators)
  • 属性装饰器(Property decorators)
  • 方法装饰器(Method decorators)
  • 参数装饰器(Parameter decorators)

tsconfig.json:

  1. {
  2. "compilerOptions": {
  3. "target": "ES5",
  4. "experimentalDecorators": true
  5. }
  6. }

装饰器使用

类装饰器

  1. function Greeter(greeting: string) {
  2. return function(target: Function) {
  3. target.prototype.greet = function(): void {
  4. console.log(greeting);
  5. };
  6. };
  7. }
  8. @Greeter("Hello TS!")
  9. class Greeting {
  10. constructor() {
  11. // 内部实现
  12. }
  13. }
  14. let myGreeting = new Greeting();
  15. myGreeting.greet(); // console output: 'Hello TS!';

方法装饰器

它接收三个参数:

  • target: Object - 被装饰的类
  • propertyKey: string | symbol - 方法名
  • descriptor: TypePropertyDescript - 属性描述符

compilerOptions 选项

  1. {
  2. "compilerOptions": {
  3. /* 基本选项 */
  4. "target": "es5", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
  5. "module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
  6. "lib": [], // 指定要包含在编译中的库文件
  7. "allowJs": true, // 允许编译 javascript 文件
  8. "checkJs": true, // 报告 javascript 文件中的错误
  9. "jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
  10. "declaration": true, // 生成相应的 '.d.ts' 文件
  11. "sourceMap": true, // 生成相应的 '.map' 文件
  12. "outFile": "./", // 将输出文件合并为一个文件
  13. "outDir": "./", // 指定输出目录
  14. "rootDir": "./", // 用来控制输出目录结构 --outDir.
  15. "removeComments": true, // 删除编译后的所有的注释
  16. "noEmit": true, // 不生成输出文件
  17. "importHelpers": true, // 从 tslib 导入辅助工具函数
  18. "isolatedModules": true, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).
  19. /* 严格的类型检查选项 */
  20. "strict": true, // 启用所有严格类型检查选项
  21. "noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
  22. "strictNullChecks": true, // 启用严格的 null 检查
  23. "noImplicitThis": true, // 当 this 表达式值为 any 类型的时候,生成一个错误
  24. "alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
  25. /* 额外的检查 */
  26. "noUnusedLocals": true, // 有未使用的变量时,抛出错误
  27. "noUnusedParameters": true, // 有未使用的参数时,抛出错误
  28. "noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
  29. "noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)
  30. /* 模块解析选项 */
  31. "moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
  32. "baseUrl": "./", // 用于解析非相对模块名称的基目录
  33. "paths": {}, // 模块名到基于 baseUrl 的路径映射的列表
  34. "rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容
  35. "typeRoots": [], // 包含类型声明的文件列表
  36. "types": [], // 需要包含的类型声明文件名列表
  37. "allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
  38. /* Source Map Options */
  39. "sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
  40. "mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
  41. "inlineSourceMap": true, // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件
  42. "inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性
  43. /* 其他选项 */
  44. "experimentalDecorators": true, // 启用装饰器
  45. "emitDecoratorMetadata": true // 为装饰器提供元数据的支持
  46. }
  47. }