打字稿:使类型适合对象文字值

时间:2018-12-29 03:19:12

标签: typescript

给定该对象文字...

const views = {
  default: 'DEFAULT',
  user: {
    home: 'HOME',
    profile: 'PROFILE'
  }
}

我希望获得一种如下所示的类型,而不必以多种方式对其进行定义,例如定义一个联合类型,然后再定义一个嵌入所有类型的对象文字

interface State {
  view: `DEFAULT' | 'HOME' | 'PROFILE'
}

我可以在Typescript中实现吗?

编辑:

我可以定义字符串的联合类型

type View = 'HOME' | 'DEFAULT' | 'PROFILE'

,然后声明对象文字(与上面的类型具有相同的值),但随后我将不得不以多种方式对其进行定义,而我将重复我自己

1 个答案:

答案 0 :(得分:1)

如果我正确地找到了您,这就是您想要的:

type View = 'HOME' | 'DEFAULT' | 'PROFILE'

interface Views {
  [key: string]: View | Views
}

const views: Views = {
  default: 'DEFAULT',
  user: {
    home: 'HOME',
    profile: 'PROFILE'
  },
  wrong: 'SOME_STRING', // error
}

UPD,在评论后。现在,如果您想将文字当作所有可能字符串的引用,则可以天真地做到这一点:

const views = {
 default: 'DEFAULT',
    user: {
      home: 'HOME',
      profile: 'PROFILE'
    },
  }

// Make some peculiar types to extract all the strings
type Views = typeof views

type Strings<Obj> = Obj[keyof Obj]
type FlatStrings<T> = T extends object ? T[keyof T] : T

type View = FlatStrings<Strings<Views>>

但是猜猜View有什么类型?只是string!与预期的DEFAULT | HOME | PROFILE不同。因为打字稿会从对象文字字符串推断类型string,除非您这样重写对象文字:

const views = {
    default: 'DEFAULT' as 'DEFAULT',
    user: {
      home: 'HOME' as 'HOME',
      profile: 'PROFILE' as 'PROFILE'
    },
  }

现在类型View具有所需的类型,但是views看起来很奇怪,不是吗?因此,我坚信您应该首先采用我的解决方案。这是专业地使用打字稿完成工作的方式,而且绝对没有双重工作(例如,IDE的VSCode工具使代码完成和处理变得容易)。