【问题标题】:How can I get tuple type from object with array of keys如何从具有键数组的对象中获取元组类型
【发布时间】:2022-08-09 19:00:58
【问题描述】:

使用从对象返回值的函数,其中包含来自对象的一些键列表,如下所示。

function mapObjToArray(obj, keys) {
    return keys.map(key => obj[key])
}

const result = mapObjToArray({ A: \"a\", B: \"b\", C: \'c\', X: \'x\'}, [\'A\', \'B\'])

我想得到结果值的确切类型,在这种情况下我的意思是[\"a\", \"b\"],但是,使用下面的代码,结果类型是(\"a\" | \"b\" | \"c\" | \"x\")[] 而不是[\"a\", \"b\"]

function mapObjToArray<T>(obj: T, keys: (keyof T)[]) {
    return keys.map(key => obj[key])
}

const result = mapObjToArray({ A: \"a\", B: \"b\", C: \'c\', X: \'x\'} as const, [\'A\', \'B\'])

我可能会在 Variadic Tuple Type 方面稍有进步,但我得到了......

function mapObjToArrayWithVariadicTuple<T, X extends [...(keyof T)[]]>(obj: T, keys: X): [...T[X[number]][]] {
    return keys.map(key => obj[key])
}

const resultVariadicTuple = mapObjToArrayWithVariadicTuple({ A: \"a\", B: \"b\", C: \'c\', X: \'x\'} as const, [\'A\', \'B\'])

越来越近,但仍然不是我想要的 typeof resultVariadicTuple (\"a\" | \"b\")[]

有没有办法得到我想要的结果类型???

TypeScript Playground

  • @ tom10271 虽然这是真的,但我认为我们可以出于问题的目的假设传入的值(和类型)是静态的

标签: typescript variadic-tuple-types


【解决方案1】:

可以肯定的一点是objkeys 参数都必须是const。 否则,由于 TypeScript 中的类型与运行时分离,返回的类型是无法确定的。

如果可以假设这个要求,那么答案应该是这样的:

type _Map<
  K extends readonly any[],
  O extends { [key in K[number]]: any }
> = K extends readonly []
  ? []
  : K extends readonly [infer H, ...infer T]
  ? [O[H], ..._Map<T, O>]
  : never;

function mapObjToArray<
  K extends readonly (string | number | symbol)[],
  O extends { [key in K[number]]: any }
>(obj: O, keys: K): _Map<K, O> {
  return keys.map((key: K[number]) => obj[key]) as any;
}

const result = mapObjToArray(
  { A: "a", B: "b", C: "c", X: "x" } as const,
  ["A", "B"] as const
);

【讨论】:

    【解决方案2】:

    我希望它有帮助

    //////////////////////////////////////////////////////////////
    // This is where the magic happens
    type Tobj<O> = {
      [key in keyof O]: [key, O[key]];
    };
    type ObjectToTuple<O> = Tobj<O>[keyof Tobj<O>];
    //////////////////////////////////////////////////////////////
    
    
    const test = {
      a: "a",
      b: "b",
      c: 1
    } as const;
    
    type T = typeof test;
    
    type TupleT = ObjectToTuple<T>;
    
    (Object.entries(test) as TupleT[]).map((entry) => {
      switch(entry[0]){
        case "a":{
          return entry[1] === "a"; // TRUE!
        }
        case "b":{
          return entry[1] === "b"; // TRUE!
        }
        case "c":{
          return entry[1] === 1; // TRUE!
        }
      }
    });
    

    【讨论】:

      猜你喜欢
      • 2023-02-24
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 2019-07-14
      • 2012-04-13
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多