“pick"的 TypeScript 泛型类型函数(结果对象值类型) [英] TypeScript generic type for "pick" function (result object values types)

查看:25
本文介绍了“pick"的 TypeScript 泛型类型函数(结果对象值类型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

选择函数的类型书写有问题.仅选择一个或多个具有相同类型值的键时,一切正常.但是如果我试图选择几个键并且它们的值是不同的类型 - 我会得到一个错误.不太确定我哪里出错了.

感谢您抽出宝贵时间.

导出接口 Mapper{(arg: T): R;}export function pick(keys: T[], obj?: O): { [K in T]: O[T] };导出函数pick(keys: T[], obj?: never): Mapper;export function pick(keys: T[], obj?: O) {const 选择器:Mapper= _obj =>keys.reduce((acc, key) => {if (key in _obj) {acc[key] = _obj[key];}返回acc;}, {} 为 O);返回对象?选择器(对象):选择器;}const obj = { someKey: 'value', otherKey: 42, moreKey: ['array value'] };const newObj = pick(['otherKey'], obj);//好的.newObj 的 TS 类型是 {otherKey: number}const n: number = newObj.otherKey;//好的const otherNewObj = pick(['otherKey', 'someKey'], obj);//不是真的好吗.otherNewObj 的 TS 类型是 {otherKey: number |字符串,someKey:数字 |细绳}const m: number = otherNewObj.someKey;//错误.输入字符串 |号码不可分配给号码

解决方案

您的映射类型有错误,您可能想使用 O[K] 而不是 O[T] 所以你最终得到 { [K in T]: O[K] }.您需要每个键 K 的类型,而不是 T 联合中所有属性的类型.

我也会使用 Pick,因为 Pick 是同态的,并且会保留诸如 readonlyoptional 之类的修饰符.

还有 obj?: never 可能不会做你想要它做的事情,任何东西都可以分配给 never,你最好在重载中省略参数:

export function pick(keys: T[], obj?: O): Pick;导出函数 pick(keys: T[]): Mapper;export function pick(keys: T[], obj?: O) {//....}

rel>rel="rel="nofollow">link

Have problem writing type for pick function. Everything works fine while picking only one key or several keys with values of same type. But if I'm trying to pick few keys and their values are different types - I will get an error. Not really sure where I made a mistake.

Thank you for your time.

export interface Mapper<T = any, R = any> {
  (arg: T): R;
}


export function pick<O, T extends keyof O>(keys: T[], obj?: O): { [K in T]: O[T] };

export function pick<T>(keys: T[], obj?: never): Mapper;

export function pick<O, T extends keyof O>(keys: T[], obj?: O) {
  const picker: Mapper<O, { [K in T]: O[T] }> = _obj =>
    keys.reduce((acc, key) => {
      if (key in _obj) {
        acc[key] = _obj[key];
      }
      return acc;
    }, {} as O);

  return obj ? picker(obj) : picker;
}

const obj = { someKey: 'value', otherKey: 42, moreKey: ['array value'] };

const newObj = pick(['otherKey'], obj);
//OK. TS type for newObj is {otherKey: number}

const n: number = newObj.otherKey;
// OK

const otherNewObj = pick(['otherKey', 'someKey'], obj);
//no really OK. TS type for otherNewObj is {otherKey: number | string, someKey: number | string}

const m: number = otherNewObj.someKey;
// Error. Type string | number is not assignable to the number

解决方案

You have an error in your mapped type you probably want to use O[K] instead of O[T] so you end up with { [K in T]: O[K] }. You want the type for each key K, not the type of all properties in the T union.

Also I would use Pick since Pick is homomorphic and would preserve modifiers such as readonly and optional.

Also obj?: never probably does not do what you want it to do, anything is assignable to never, you are better off omitting the parameter in that overload:

export function pick<O, T extends keyof O>(keys: T[], obj?: O): Pick<O, T>;
export function pick<T>(keys: T[]): Mapper;
export function pick<O, T extends keyof O>(keys: T[], obj?: O) {
    //....
}

Playground Link

这篇关于“pick"的 TypeScript 泛型类型函数(结果对象值类型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆