TypeScript 泛型函数重载 and/or 类型保护
TypeScript generic function overloading and/or type guard
我正在尝试使用通用函数以这种方式提取枚举和对象的键和值:
type Key = string | number | symbol;
type Dictionary<K extends Key, T> = Partial<Record<K, T>>;
type Obj = Dictionary<Key, unknown>; // stricter than object
type Enum = Dictionary<number, string>; // stricter than enum
function keys<K extends Key, T>(record: Record<K, T>): Array<K> {
return Object.keys(record) as Array<K>;
}
function values<K extends Key, T>(record: Record<K, T>): Array<T> {
return keys(record).map((key) => record[key]);
}
问题是 Object.keys(anything) returns string[] 无论任何东西的键是什么,更糟糕的是,当任何东西是枚举时,它 returns 也是数值作为字符串(恕我直言,这显然是错误的),所以我为这种情况编写了一个特定的函数:
function keys(record: Enum): Array<number> {
return Object.keys(record)
.map((x) => parseInt(x))
.filter((x) => !isNaN(x));
}
现在如何将这段代码合并到通用键函数中?在 K 上有一个类型保护,以防它是我猜的数字,但我尝试了很多方法都没有成功...
顺便说一句,是否有一个“纯 TypeScript”库已经做到了这一点?
这不直观 - 但从 Object.keys 假设 keyof T 实际上是不正确的 - 请参阅 以获得完整解释 - 但 TLDR 是要记住 TS 不执行对象过量 属性 检查和潜在的运行时原型污染。
如果我理解你的问题 - 我相信你可以在你的过滤语句中使用 Extract 从 Enum 中提取数字键。
function keys<E extends Enum>(record: E): Extract<keyof E, number>[] {
return Object.keys(record)
.map((x) => parseInt(x))
.filter((x): x is Extract<keyof E, number> => !isNaN(x));
}
const res = keys(foo); // res: (0 | 1 | 124124)[]
我正在尝试使用通用函数以这种方式提取枚举和对象的键和值:
type Key = string | number | symbol;
type Dictionary<K extends Key, T> = Partial<Record<K, T>>;
type Obj = Dictionary<Key, unknown>; // stricter than object
type Enum = Dictionary<number, string>; // stricter than enum
function keys<K extends Key, T>(record: Record<K, T>): Array<K> {
return Object.keys(record) as Array<K>;
}
function values<K extends Key, T>(record: Record<K, T>): Array<T> {
return keys(record).map((key) => record[key]);
}
问题是 Object.keys(anything) returns string[] 无论任何东西的键是什么,更糟糕的是,当任何东西是枚举时,它 returns 也是数值作为字符串(恕我直言,这显然是错误的),所以我为这种情况编写了一个特定的函数:
function keys(record: Enum): Array<number> {
return Object.keys(record)
.map((x) => parseInt(x))
.filter((x) => !isNaN(x));
}
现在如何将这段代码合并到通用键函数中?在 K 上有一个类型保护,以防它是我猜的数字,但我尝试了很多方法都没有成功...
顺便说一句,是否有一个“纯 TypeScript”库已经做到了这一点?
这不直观 - 但从 Object.keys 假设 keyof T 实际上是不正确的 - 请参阅
如果我理解你的问题 - 我相信你可以在你的过滤语句中使用 Extract
function keys<E extends Enum>(record: E): Extract<keyof E, number>[] {
return Object.keys(record)
.map((x) => parseInt(x))
.filter((x): x is Extract<keyof E, number> => !isNaN(x));
}
const res = keys(foo); // res: (0 | 1 | 124124)[]