简体   繁体   English

TypeScript 通用 function 重载和/或类型保护

[英]TypeScript generic function overloading and/or type guard

I'm trying to have generic function to extract keys and values of enums and objects this way:我正在尝试使用通用 function 以这种方式提取枚举和对象的键和值:

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]);
}

the problem is that Object.keys(anything) returns string[] whatever the keys of anything are, and even worse, when anything is an enum, it returns also the numeric values as strings (which is clearly wrong IMHO), so I wrote a specific function for this case:问题是 Object.keys(anything) 返回 string[] 无论任何东西的键是什么,更糟糕的是,当任何东西是枚举时,它也返回数值作为字符串(恕我直言,这显然是错误的),所以我写了这个案例的特定 function:

function keys(record: Enum): Array<number> {
  return Object.keys(record)
    .map((x) => parseInt(x))
    .filter((x) => !isNaN(x));
}

now how can I merge this code in the generic keys function?现在如何将此代码合并到通用密钥 function 中? with a type guard on the K in case it is a number I guess, but I tried so many ways without success...在 K 上有一个类型保护,以防它是我猜的数字,但我尝试了很多方法都没有成功......

BTW is there a "pure TypeScript" lib around that already does this?顺便说一句,是否有一个“纯 TypeScript”库已经做到了这一点?

It's not intuitive - but it's actually incorrect to assume keyof T from Object.keys - see https://stackoverflow.com/a/55012175/2310450 for a full explanation - but the TLDR is to bear in mind TS not performing object excess property checks and potential runtime prototype pollution.这不直观 - 但从 Object.keys 假设 keyof T 实际上是不正确的 - 请参阅https://stackoverflow.com/a/55012175/2310450以获得完整解释 - 但 TLDR 是要记住 TS 不执行 object 多余的财产检查和潜在的运行时原型污染。

If I understand your question correctly - I believe you can use Extract<keyof T, number> in your filter statement to pull out numerical keys from Enum.如果我正确理解你的问题 - 我相信你可以在你的过滤器语句中使用 Extract<keyof T, number> 从 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)[]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM