Search code examples
typescripttypesinternationalizationtranslationtypescript-typings

Typescript - translation strings typings solution?


I'm using this object format to store translation strings for multiple languages:

export const Translations = {
  'en': {
    text1: 'Hello world!',
    text2: 'Login'
  }
  'cs': {
    text1: 'Ahoj svět!',
    text2: 'Přihlášení'
  }
}

Then I have my state and an interface for the state defined:

export const MyState: State = {
  lang: 'cs',
  trans: Translations.cs,
}

export type State = {
  lang: LangCodes,
  trans: ???
}

Now I would need somehow to define that MyState.trans can contain only names of translation properties, which means text1, text2 in this case. Something that enables type checkings an autocomplete feature in editor for this object (when using like this: MyState.trans.text1). Can it be done?


Solution

  • I believe union of all possible/allowed state should help:

    export const Translations = {
      'en': {
        text1: 'Hello world!',
        text2: 'Login'
      },
      'cs': {
        text1: 'Ahoj svět!',
        text2: 'Přihlášení'
      }
    } as const
    
    type Translations = typeof Translations
    type LangCodes = keyof Translations
    
    type Values<T> = T[keyof T]
    
    // Make union of all allowed states
    type Union = {
      [P in LangCodes]: {
        lang: P,
        trans: Translations[P]
      }
    }
    
    // get all values of the union
    type State = Values<Union>
    
    export const MyState: State = {
      lang: 'cs',
      trans:Translations.cs
    } // ok
    
    export const MyWrongState: State = {
      lang: 'cs',
      trans:Translations.en
    } // error
    

    Playground

    P.S. My main goal is to make invalid state unrepresentable