【问题标题】:How to convert type object keys into an array of strings type in typescript如何在打字稿中将类型对象键转换为字符串类型的数组
【发布时间】:2020-08-15 15:56:29
【问题描述】:

在打字稿中给出以下输入:

type InputObjectType = {
  a: string
  b: number
  c: {}
}

我怎样才能得到以下类型:

type ObjectKeysArrayType = ['a', 'b', 'c']

到目前为止,我只能做到:

type AllPossibleKeys = (keyof InputObjectType)[]

这给了我["a" | "b" | "c"],这很接近,但在这种情况下不是我想要的。

我需要一个始终包含给定类型对象中所有键字符串的数组。我知道强制执行此操作的唯一方法,例如,当用户向对象添加新键时,该键也添加到数组中时,就是通过类似这样的方法。

【问题讨论】:

  • InputObject 是类型还是对象?名称说明一件事,而代码说明另一件事。
  • 我已经更新了代码,它应该是一个类型。
  • 好的,现在你能解释一下这样的 String Array Literal 类型会有什么用吗?因为也许根本问题是您应该问的问题。类型在输出中被擦除,因此它们的唯一用途是用于静态类型检查,或构造其他类型以进行静态类型检查。在后一种情况下,keyof InputObjectType 就是您所需要的。否则,这似乎是一个没有目的的抽象练习,并且可能不属于 SO。 换句话说,假设你问的是不可能的,我认为不可能。向 Typescript 的人说明为什么应该这样做。
  • 另外,请将标题更改为与问题一致,或相反。
  • 你所拥有的应该可以工作(尽管我使用的是 v3.9)。当我执行相同的步骤时,我会得到("a"|"b"|"c")[],我相信这正是您想要的。相反,如果您想要一个动态包含所有这些值的数组,我认为这是不可能的,因为该类型在运行时不存在。

标签: typescript


【解决方案1】:

我使用两种方法:

// Option 0: Define type using object
const someTypeExample = {
  a: 1,
  b: 'str',
  c: 'foo' as 'foo'|'bar'
};

type SomeType0 = typeof someTypeExample;


// Option 1: If object stores different types
type SomeType = {
  a: number;
  b: string;
}

const typeVar: SomeType = {
    a: 10,
    b: 'string'
}

// used for typechecking
type SomeTypeKey = keyof SomeType;

// create an array to be used in runtime
// disadvantage is that properties need to be repeated
const keys: SomeTypeKey[] = ['a', 'b']; // type checked
// TODO what I'm missing is:
// const keys = keys<SomeTypeKey>(); that would return ['a', 'b'] during transpiling
// ie. native support of https://github.com/kimamula/ts-transformer-keys 
// which is out of scope for TS: https://github.com/microsoft/TypeScript/issues/13267
let isValidKey = keys.includes('c' as SomeTypeKey)


// Option 2: start from keys array definition, in case all values have the same type

const myKeys = ['foo', 'bar'] as const; // as const does the magic
type MyKey = typeof myKeys[number]; // = 'foo' | 'bar'

type MyMap = Record<MyKey, string>;
type MyMap2 = { [key in MyKey]: string };

【讨论】:

    【解决方案2】:

    不确定您是否仍在此处寻找解决方案,但希望这会有所帮助。

    如果你想要的是一个类型,它要求变量是一个字符串数组,只包含与你的对象的键相等的值,那么你列出的应该可以工作。

    type InputObjectType = {
      a: string
      b: number
      c: {}
    }
    
    type AllPossibleKeys = (keyof InputObjectType)[]
    

    AllPossibleKeys 将是等于("a"|"b"|"c")[] 的类型。这看起来是您所要求的,但有一个警告,我猜您想如何使用它。

    const fieldArray1: AllPossibleKeys = ['a', 'b', 'c']; //valid
    const fieldArray2: AllPossibleKeys = ['a', 'b', 'c', 'd']; //will throw a Typescript error
    const fieldArray3: AllPossibleKeys = ['a', 'b']; //this is also valid though as each member is a valid value
    

    如果你想要一个类型中所有键的数组,我知道没有办法明确地做到这一点。但是,如果您能够使用接口而不是类型,那么您可以执行以下操作:

    import { keys } from 'lodash';
    
    interface InputObject = {
      a: string
      b: number
      c: {}
    }
    
    class InputObjectStub implements InputObject {
      a = null;
      b = null;
      c = null;
    }
    
    const fieldArray1 = keys(new InputObjectStub()); //returns ['a', 'b', 'c']
    

    但请注意,这不会强制执行可选属性。如果您需要这样做,请将您的类定义更改为 class InputObjectStub implements Required&lt;InputObject&gt; {...

    编辑:拼写

    【讨论】:

    • keyof 是关键
    【解决方案3】:

    目前不可能,因为类型信息在运行时不可用。您可以在Typescript Playground 上试用您的代码。当你这样做时,你会发现这段代码:

    type InputObjectType = {
      a: string
      b: number
      c: {}
    }
    

    被转译为空。将代码转换为 javascript 后,它根本不存在。由于它在运行时不存在,因此无法执行任何运行时操作,例如遍历其属性,甚至打印出来。

    【讨论】:

    • 我不是在运行时寻找这个信息,我想要它用于类型检查。
    • 试着在你的问题中描述你想要做什么。如果人们了解您的用例,他们可能会建议正确的方法。
    【解决方案4】:

    试试这个

    const object1 = {
      a: 'somestring',
      b: 42,
      c: false
    };
    
    console.log(Object.keys(object1));
    
    output: Array ["a", "b", "c"]
    

    【讨论】:

    • 你能在类型中使用Object.keys(object1)吗?我很确定不是,我得到'Object' only refers to a type, but is being used as a namespace here.
    • 这与所要求的不同。
    • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常质量更高,更有可能吸引投票。
    猜你喜欢
    • 2020-11-21
    • 2020-05-08
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多