typescript - 是否可以在 TypeScript 中精确键入 _.invert?

标签 typescript lodash typescript-generics typescript-declarations

在 lodash 中,_.invert函数反转对象的键和值:

var object = { 'a': 'x', 'b': 'y', 'c': 'z' };

_.invert(object);
// => { 'x': 'a', 'y': 'b', 'z': 'c' }

lodash 类型 currently声明它总是返回一个 stringstring 映射:

_.invert(object);  // type is _.Dictionary<string>

但有时,尤其是当您使用 const assertion 时,更精确的类型将是合适的:

const o = {
  a: 'x',
  b: 'y',
} as const;  // type is { readonly a: "x"; readonly b: "y"; }
_.invert(o);  // type is _.Dictionary<string>
              // but would ideally be { readonly x: "a", readonly y: "b" }

有没有可能让打字如此精确?此声明接近:

declare function invert<
  K extends string | number | symbol,
  V extends string | number | symbol,
>(obj: Record<K, V>): {[k in V]: K};

invert(o);  // type is { x: "a" | "b"; y: "a" | "b"; }

键是正确的,但值是输入键的并集,即你失去了映射的特异性。有可能做到这一点吗?

最佳答案

编辑

由于在映射类型中引入了 as 子句,您可以将此类型写为:


You can use a mapped type with an as clause:

type InvertResult<T extends Record<PropertyKey, PropertyKey>> = {
  [P in keyof T as T[P]]: P
}

Playground Link

原始答案

您可以使用保留正确值的更复杂的映射类型来做到这一点:

const o = {
    a: 'x',
    b: 'y',
} as const;

type AllValues<T extends Record<PropertyKey, PropertyKey>> = {
    [P in keyof T]: { key: P, value: T[P] }
}[keyof T]
type InvertResult<T extends Record<PropertyKey, PropertyKey>> = {
    [P in AllValues<T>['value']]: Extract<AllValues<T>, { value: P }>['key']
}
declare function invert<
    T extends Record<PropertyKey, PropertyKey>
>(obj: T): InvertResult<T>;

let s = invert(o);  // type is { x: "a"; y: "b"; }

Playground Link

AllValues 首先创建一个包含所有 keyvalue 对的联合(因此对于您的示例,这将是 { key: “a”;值:“x”;} | { 键:“b”;值:“y”;})。在映射类型中,我们然后映射联合中的所有 value 类型,对于每个 value,我们使用 Extract< 提取原始 key/。只要没有重复值,这就会很好地工作(如果有重复值,我们将在值出现的地方获得键的并集)

关于typescript - 是否可以在 TypeScript 中精确键入 _.invert?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56415826/

相关文章:

angular - mat-step onclick 事件函数

javascript - 根据对象内的值获取对象键

typescript - 仅覆盖一些通用变量

typescript - TS - 如何对泛型类型内的类型值执行字符串函数

typescript - 如何拒绝异步/等待语法?

javascript - 在 Angular 5 中隐藏 ngFor 的一部分

reactjs - 如何使用 Lerna 和 Yarn Workspaces 在 Typescript monorepo 中启用热重载?

javascript - 如何使用 lodash 做 deep _.omitby

javascript - 在 react 中多次触发反跳

typescript - 从函数参数推断联合类型