简体   繁体   中英

typescript: make type that fits object literal values

given this object literal...

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

I want to get a type like below without having to define it in multiple ways like defining a union type and then an object literal with all the types embedded

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

Can I achieve this in Typescript?

EDIT:

I could defined a union type of strings

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

and then declare the object literal (with the same values as the type above) but then I would have to define it in multiple ways and I would be repeating myself

If I got you correctly, this is what you want:

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, after comments. Now, if you want to object literal be a reference of all possible strings you could naively do this:

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>>

But guess what type does View have? It's just string ! Not DEFAULT | HOME | PROFILE DEFAULT | HOME | PROFILE DEFAULT | HOME | PROFILE as expected. Because typescript infers type string from object literal strings unless you rewrite the object literal like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM