如何在打字稿中使用动态键键入函数返回类型?

时间:2021-03-25 12:50:50

标签: javascript typescript generics

我有一个返回对象的函数,如下所示:

// keyValue would be something like 'end', 'start' etc.

const getTimeAndDateSplit = (keyValue: string, isoDateString) => {
  // do time parsing

  return {
    [`${keyValue}Date`]: 'dd/mm/yyy',
    [`${keyValue}Time`]: 'hh:mm'
  }
}

现在我已经尝试使用泛型以多种不同的方式输入它,或者只是输入变量类型无济于事:

const startTimeKeyValues: {
  startDate: string;
  startTime: string;
} = getTimeAndDateSplit("start", startTime);
// Type '{ [x: string]: string; }' is missing the following properties from type '{ startDate: string; startTime: string; }': startDate, startTimets(2739)

返回类型始终为 { [x: string]: string }

如何输入 getTimeAndDateSplit 以便轻松传递返回值,例如 getTimeAndDateSplit<"startDate", "startTime">

1 个答案:

答案 0 :(得分:0)

您可以在 Record 类型的帮助下实现此行为。

参见示例:


const record = <K extends string, V>(key: K, value: V) => ({ [key]: value }) as Record<K, V>;

const getTimeAndDateSplit = <T extends string>(keyValue: T) => ({
    ...record(`${keyValue}Date` as const, 'dd/mm/yyy' as const),
    ...record(`${keyValue}Time` as const, 'hh:mm' as const),
})

const startTimeKeyValues = getTimeAndDateSplit("start");

因为具有计算字符串的对象被评估为 {[prop: string]:any},所以我们应该承担责任并将此对象显式转换为 Record

如果你不喜欢类型转换,你可以使用重载:


function record<K extends string, V>(key: K, value: V): Record<K, V>
function record<K extends string, V>(key: K, value: V) {
    return ({ [key]: value })
}

但是请记住,对函数使用一个重载是一种不好的做法,它实际上与前面的示例相同。