常量值的Typescript通用参数

时间:2019-10-27 08:15:08

标签: typescript

是否可以使用带有通用参数的const值?

对于此代码

import * as R from 'ramda';

enum ApiActionType {
  requested,
  completed,
  failed,
  cancelled,
}

type ApiActionTypeKeys = keyof typeof ApiActionType;

enum ChangedActionType {
  changed,
}

type ChangedActionTypeKeys = keyof typeof ChangedActionType;

const getActionType = <TPrefix, TActionTypeKeys extends string>(
  keys: TActionTypeKeys[]
) => (
  prefix: TPrefix
): Record<TActionTypeKeys, [TPrefix, TActionTypeKeys]> => {
  return R.pipe(
    R.map(k => [k, [prefix, k]] as [TActionTypeKeys, [TPrefix, TActionTypeKeys]]),
    R.fromPairs as () => Record<TActionTypeKeys, [TPrefix, TActionTypeKeys]>
  )(keys);
}

// const createApiActionType: <TPrefix>(prefix: TPrefix) => Record<"requested" | "completed" | "failed" | "cancelled", [TPrefix, "requested" | "completed" | "failed" | "cancelled"]>
const createApiActionType = <TPrefix>(prefix: TPrefix) => getActionType<TPrefix, ApiActionTypeKeys>(R.keys(ApiActionType))(prefix)
// const createChangedctionType: <TPrefix>(prefix: TPrefix) => Record<"changed", [TPrefix, "changed"]>
const createChangedctionType = <TPrefix>(prefix: TPrefix) => getActionType<TPrefix, ChangedActionTypeKeys>(R.keys(ChangedActionType))(prefix)

是否可以将最后两行简化到下面,而不会丢失结果函数的泛型参数?即保留TPrefix通用参数,而不要成为前缀类型为unknown的非通用函数

// const createApiActionType: (prefix: unknown) => Record<"requested" | "completed" | "failed" | "cancelled", [unknown, "requested" | "completed" | "failed" | "cancelled"]>
const createApiActionType = getActionType(R.keys(ApiActionType))
// const createChangedctionType: (prefix: unknown) => Record<"changed", [unknown, "changed"]>
const createChangedctionType = getActionType(R.keys(ChangedActionType))

1 个答案:

答案 0 :(得分:2)

给出一个咖喱getActionType函数声明

declare const getActionType: <TPrefix, TActionTypeKeys extends string>(
  keys: TActionTypeKeys[]
) => (
    prefix: TPrefix
  ) => Record<TActionTypeKeys, [TPrefix, TActionTypeKeys]>

,不为内部函数保留通用类型参数TPrefix,而是使用default unknown类型实例化。 TS在getActionType的外部函数签名中寻找一个代码位置来推断其类型实参,然后回退到unknown,因为TPrefix在这里未使用。 Example

declare const apiActionTypeKeys: ApiActionTypeKeys[]

// (prefix: unknown) => Record<ApiActionTypeKeys, [unknown, ChangedActionTypeKeys]>
const createChangedctionType = getActionType(apiActionTypeKeys)

我们可以通过在内部函数上定义TPrefix来解决此问题。

declare const getActionType: <TActionTypeKeys extends string>(
    keys: TActionTypeKeys[]
) => <TPrefix>(prefix: TPrefix) => Record<TActionTypeKeys, [TPrefix, TActionTypeKeys]>

并对其进行测试:

declare const apiActionTypeKeys: ApiActionTypeKeys[]
declare const changedActionTypeKeys: ChangedActionTypeKeys[]

// <TPrefix>(prefix: TPrefix) => Record<ApiActionTypeKeys, [TPrefix, ApiActionTypeKeys]>
const createApiActionType = getActionType(apiActionTypeKeys)

// "requested" | "completed" | "failed" | "cancelled"
const result = createApiActionType("fooPrefix").cancelled[1]

Full example

希望,有帮助!