dataset 类型封装:教你如何掌握 TS 函数重载

247 阅读1分钟

如果帮助到你,不妨点个赞 ❤️

问题

无类型提示:

const { hello } = event.currentTarget.dataset // hello 无类型提示

解决

使用函数重载。函数重载有 3 个重要点:

  1. 分成 Overload signatures 和 Implementation signature
  2. Implementation 必须足够 general 来包容 Overload signatures
  3. 只有 Overload signatures 才能被调用

一般记住第一点即可,遇到问题在看 2、3 点。

// Overload signatures 🔥
export function getDataset<D extends Record<string, any>>(
  event: IEvent<D>,
): Partial<D>;
export function getDataset<D extends Record<string, any>>(
  event: IEvent<D>,
  key: keyof D,
): D[keyof D] | undefined;

// Implementation signature 🔥

/**
 * 强类型的 getDataset,防止 NPE。建议开启 TS strict 模式!
 *
 * Page({
 *   onTap(event: IEvent<{ hello: string; world: string }>) {
 *     const hello = getDataset(myEvent, 'hello');
 *
 *     // 如果取多个值
 *    const { hello, world } = getDataset(myEvent)
 *   }
 * })
 *
 * @param event
 * @param key
 * @returns
 * @example
 * // 使用方式一:显示传入 dataset 的类型
 * // `shouldSayHello` should be `string | undefined`;
 * const shouldSayHello = getDataset<{ hello: string }>(event, 'hello');
 *
 * // `dataset` should be `{ hello: string | undefined }`;
 * const dataset = getDataset<{ hello: string }>(event);
 *
 * // 使用方式二:定义 event 类型,让其自动推导
 * interface IEvent<D extends Record<string, any>> {
 *   currentTarget: {
 *     dataset: D;
 *   };
 * }
 *
 * const myEvent: IEvent<{ hello: string }> = { currentTarget: { dataset: { hello: 'str' } } }
 * // dataset.hello should be `string` | `undefined;`
 * const dataset = getDataset(myEvent);
 *
 * // `shouldSayHello` should be `string` | `undefined`;
 * const shouldSayHello = getDataset(myEvent, 'hello');
 */
export function getDataset<D extends Record<string, any>>(
  event: IEvent<D>,
  key?: keyof D,
): unknown {
  const { dataset } = event.currentTarget;

  if (key) {
    return dataset[key];
  }

  return dataset;
}

interface IEvent<D extends Record<string, any>> {
  currentTarget: {
    dataset: D;
  };
}

效果:

const myEvent = { currentTarget: { dataset: { hello: 'false' } } }

// dataset.hello should be `string` | `undefined;`
const dataset = getDataset(myEvent); 

// `shouldSayHello` should be `string` | `undefined`;
const shouldSayHello = getDataset(myEvent, 'hello'); 

getDataset 的返回值有类型,且能自动根据第二个参数的有无变化,其次第二个参数有智能提示和校验,即如果传入的 key 非预期会报错。

image.png

参考

dmitripavlutin.com/typescript-…