首页 > 解决方案 > 打字稿动态界面

问题描述

我有一个函数要转换为泛型 Typescript 以作为实用程序提供。我已经达到了它,但是当一个函数返回一个函数时会发生什么。我知道这不是必需的,但仍然

/**
 * createConstants Type
 */
type createConstantsType =
  <T extends string, U extends string>(namespace: T, prefix: U | null) =>
    <V extends string>(...constants: V[]) => Record<V, string>;

/**
 * function for creating namespaced constants
 * @param {String} namespace the namespace for the constant to create
 * @param {String} prefix the prefix for the constant to create
 * @returns {Object} namespaced constants for a module/feature
 * 
 *    // Common approach
 *    export const NAMESPACE = 'manual';
 *    export const SIDEBAR_TOGGLE = `${NAMESPACE}/SIDEBAR_TOGGLE`;
 *    export const SIDEBAR_OPEN = `${NAMESPACE}/SIDEBAR_OPEN`;
 *    export const SIDEBAR_CLOSE = `${NAMESPACE}/SIDEBAR_CLOSE`;
 *
 *    // Usage of this utility
 *    export const NAMESPACE = 'manual';
 *    export const SIDEBAR = createConstants(NAMESPACE, 'sidebar')('TOGGLE', 'OPEN', 'CLOSE');
 *
 *    // which will generate:
 *    SIDEBAR = {
 *      TOGGLE: 'manual/SIDEBAR_TOGGLE',
 *      OPEN: 'manual/SIDEBAR_OPEN',
 *      CLOSE: 'manual/SIDEBAR_CLOSE',
 *    }
 * 
 */
export const createConstants: createConstantsType =
  <T extends string, U extends string>(namespace: T, prefix: U | null = null) =>
    <V extends string>(...constants: V[]): Record<V, string> => (
    constants.reduce((result: Record<V, string>, constant: string): Record<V, string>  => ({
      [constant.toUpperCase()]:
        `${namespace}/${(prefix) ? `${prefix.toUpperCase()}_` : ''}${constant.toUpperCase()}`,
      ...result,
    }), {} as Record<V, string>)
  );

标签: typescript

解决方案


有几点需要注意:

  • String当你的意思是 时不要使用string。大写字母是对StringJavaScript 中全局对象的引用。
  • 避免将函数定义为Function. 的定义Function非常广泛,即使你的函数使用了一些精确的类型和泛型,TypeScript 也会忽略所有这些,因为它被告知将其视为 any Function。如果要创建函数类型,请以这种方式编写其签名:type MyFunction = (argument: number) => boolean改为。
  • 根据经验,如果您的参数是 type string,您可以从创建一个类型参数(泛型)并说出它开始extends string。所以,<T extends string>(argument: T)而不是(argument: string).

当您应用这些规则时,您的解决方案将如下所示:

export const createConstants = <T extends string, U extends string>(namespace: T, prefix: U | null = null) => <V extends string>(...constants: V[]): Record<V, string> => (
  constants.reduce((result, constant) => ({
    [constant.toUpperCase()]: 
      `${namespace}/${(prefix) ? `${prefix.toUpperCase()}_` : ''}${constant.toUpperCase()}`,
    ...result,
  }), {} as Record<V, string>)
);

const test = createConstants('manual', 'SIDEBAR')('TOGGLE', 'OPEN', 'CLOSE')

请参阅TypeScript 游乐场


推荐阅读