0

I'm building an Nuxt.js billingual Blog with TypeScript. The application consumes data from an REST API. The data is structured like this:

{
  "Headline_de": "Mein erster Blogpost",
  "Headline_en": "My first Blogpost",
}

Getting the data from the API for one language looks like this:

export const mutations = {
  setCurrentBlogpost(state, blogpostId) {
    const currentBlogpost = await axios.get(api + blogpostId);
    
    const normalizedBlogpost = {
      headline: currentBlogpost.Headline_de,
    };
    state.commit('setCurrentBlogpost', currentBlogpost.data);
  }
};

Now I want to get the data, depending on which language currently is chosen. I already tried to manipulate the property like this:

const headline = 'currentBlogpost.Headline_' + this.$i18n.locale; // prints de or en

export const mutations = {
  setCurrentBlogpost(state, currentBlogpost) {
    const normalizedBlogpost = {
      headline: headline,
    };
    state.currentBlogpost = normalizedBlogpost;
  }
};

But now, it just sets the property as a String. Is there a way to manipulate the input properties, for my issue?

Edit: I got it running like this. But I feel like, there is a way simpler way to achieve this.

 setCurrentBlogpost(state, currentBlogpost) {

    if (this.$i18n.locale == 'de') {
      const normalizedBlogpost: Blogpost = {
        headline: currentBlogpost.Headline_de,
      };
      state.currentBlogpost = normalizedBlogpost;
    }

    if (this.$i18n.locale == 'en') {
      const normalizedBlogpost: Blogpost = {
        headline: currentBlogpost.Headline_en,
      };
      state.currentBlogpost = normalizedBlogpost;
    }
  }
2
  • Yes, you can access properties using strings via [] operator where you state the property name (key), for example, currentBlogpost.Headline_de is equivalent to currentBlogpost["Headline_de"]. Commented Dec 7, 2020 at 18:45
  • @ZdeněkJelínek wow. this is great. thank you very much! I added an answer, implementing your solution. Thank you very much!! Commented Dec 7, 2020 at 19:00

2 Answers 2

2

The right thing to do is to index into currentBlogpost via bracket access, like currentBlogpost[headline], where headline is either "Headline_en" or "Headline_de".

Furthermore, as of TypeScript 4.1, if you use a template literal to represent your headline string, you can use a template literal const assertion to get a template literal type. Specifically, the template literal `Headline_${this.$i18n.locale}` as const will be evaluated as the type "Headline_en" | "Headline_de":

  $i18n = {
    locale: Math.random() < 0.5 ? "de" as const : "en" as const
  }

  method() {
    const currentBlogpost = {
      "Headline_de": "Mein erster Blogpost",
      "Headline_en": "My first Blogpost",
    }
    const headline = `Headline_${this.$i18n.locale}` as const;
    const normalizedBlogpost = {
      headline: currentBlogpost[headline], // <-- this type checks!
     };
  }

Before TS4.1, headline would only be seen as type string by the compiler, which is too wide to use as a property key of currentBlogpost without a type assertion:

const headline = "Headline_"+this.$i18n.locale; // string
const normalizedBlogpost = {
  headline: currentBlogpost[headline], // error!  No index signature 
};

Playground link to code

Sign up to request clarification or add additional context in comments.

Comments

0

Thanks to @Zdeněk Jelínek, I could already implement a more efficient solution. I implemented it like this and it works:

  setCurrentBlogpost(state, currentBlogpost) {
    const locale = this.$i18n.locale;

    const normalizedBlogpost: Blogpost = {
      headline: currentBlogpost['Headline_' + locale],
    };
    state.currentBlogpost = normalizedBlogpost;
  }
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.