TypeScript 中的编程技巧

INFO

本文应该会持续更新...

私有化构造函数实现工具类

平时开发的时候我们实现工具类大多是以方法的形式导出,例如:

// index.ts
// export
export const utils = () => {
  console.log('...')
}

使用:

// useage.ts
// useage
import { utils } from './index.ts'
utils()

我么看一下如何通过 Class 的形式来构建工具函数 TypeScript 提供了 private/protected/public 几个修饰符。
来简单看一下这个几个修饰符号的对比:

privateprotectedpublic
公开的,默认的,谁都可以使的受保护的,仅基类和派生类可以使用,外部不可使用私有的,仅自己可以使用,子类和外部都不可以使用

在 TS 中 constructor 默认是 public 修饰的。可以通过 new 关键字实例化。但某些场景下,私有化类的构造函数还有其他的妙用。

class Utils {
  private constructor() {}
  static sayHello() {
    console.log("hello")
  }
}
// usage
Utils.sayHello()
// 这样会报错
// Constructor of class 'Utils' is private and only accessible within the class declaration.(2673)
const utils = new Utils() 









 
 

这里用到了 static 关键字, static 关键字来标识一个成员为静态成员,不同于实例成员,在类的内部静态成员无法通过 this 来访问,需要通过 Utils.sayHello 的形式访问。 关于 static,可以看一下上面的代码,编译成 es5 后是什么样的。

"use strict";
var Utils = /** @class */ (function () {
  function Utils() {
  }
  Utils.sayHello = function () {
    console.log("hello");
  };
  return Utils;
}());
Utils.sayHello();

可以看到 sayHello 是直接挂载到函数上的,而不是原型上的。
思考一下:如何可以挂载到原型上?

利用 Bottom Type never 处理分支检查

先简单了解下 never, never 可以说是其他所有类型的子类型,never 存在的意义是描述根本不存在的类型

type A = string & number // never

下面就基于 never 的推断,简单实现一下分支检查

type strOrNumOrBool = string | number | boolean

const test = (strOrNumOrBool: strOrNumOrBool) => {
  if (typeof strOrNumOrBool === 'string') { // strOrNumOrBool
    strOrNumOrBool.charAt(1);
  } else if (typeof strOrNumOrBool === 'number') { // number | boolean
    strOrNumOrBool.toFixed();
  } else if (typeof strOrNumOrBool === 'boolean') { // boolean
    strOrNumOrBool === true;
  } else {
    const _exhaustiveCheck = strOrNumOrBool; // never
    throw new Error(`Unknown input type: ${_exhaustiveCheck}`);
  }
}
// 其中每一个 `if` 分支都会收窄 strOrNumberOrBool 的类型,
// 三个分支过后 strOrNumOrBool 就是 never 了。