Sentiment analysis is usually a task that requires a specialised dataset and machine-learning techniques to implement properly. However, I thought it might be a nice exercise to try and implement sentiment analysis with TypeScript without training models.
// Define a type for the sentiment result type Sentiment = 'positive' | 'neutral' | 'negative'; // Class to perform sentiment analysis on a given text class SentimentAnalysis { // Arrays of positive and negative words to use in the analysis private positiveWords = ["love", "like", "great", "good", "happy", "awesome"]; private negativeWords = ["hate", "dislike", "bad", "angry", "sad", "terrible"]; // Method to perform sentiment analysis on a given text public getSentiment(text: string): { sentiment: Sentiment, positiveWords: number, negativeWords: number, neutralWords: number } { // Convert the text to lowercase to make the analysis case-insensitive const lowerText = text.toLowerCase(); // Sum up the number of times each positive word appears in the text let positiveScore = this.positiveWords.reduce((acc, word) => { // Use a regular expression to match the word in the text return acc + (lowerText.match(new RegExp(word, 'g')) || []).length; }, 0); // Sum up the number of times each negative word appears in the text let negativeScore = this.negativeWords.reduce((acc, word) => { // Use a regular expression to match the word in the text return acc + (lowerText.match(new RegExp(word, 'g')) || []).length; }, 0); // Calculate the number of neutral words by subtracting the positive and negative words from the total number of words let neutralScore = lowerText.split(' ').length - positiveScore - negativeScore; // Compare the number of positive and negative words and return the sentiment result if (positiveScore > negativeScore) { return { sentiment: "positive", positiveWords: positiveScore, negativeWords: negativeScore, neutralWords: neutralScore }; } else if (positiveScore < negativeScore) { return { sentiment: "negative", positiveWords: positiveScore, negativeWords: negativeScore, neutralWords: neutralScore }; } else { return { sentiment: "neutral", positiveWords: positiveScore, negativeWords: negativeScore, neutralWords: neutralScore }; } } } // Create an instance of the SentimentAnalysis class const sentimentAnalysis = new SentimentAnalysis(); // Analyze some sample text const result = sentimentAnalysis.getSentiment("I love this code and think it is great!"); // Log the result console.log(result);
This code uses a class called SentimentAnalysis
to perform sentiment analysis on a given text. The class has two arrays of positive and negative words and a method called getSentiment
that performs the analysis.
The method first converts the text to lowercase and then uses two calls to reduce, to sum up, the number of times each positive and negative word appears in the text. It then calculates the number of neutral words by subtracting the positive and negative words from the total number of words. Finally, it compares the number of positive and negative words and returns a result that includes the sentiment and the number of positive, negative, and neutral words found.
While this code isn’t scientific because it doesn’t perform a deep analysis beyond breaking up a string into words, nor does it account for all positive, negative and neutral words, it’s a cool little implementation you could use for basic purposes.
Testing our code
Because testing is very important and provides a great way to understand code, we will write some Jest unit tests for our sentiment analysis. It’s a basic implementation, but writing tests is a good habit to get into.
import SentimentAnalysis from "./sentiment-analysis"; describe("SentimentAnalysis", () => { let sentimentAnalysis: SentimentAnalysis; beforeEach(() => { sentimentAnalysis = new SentimentAnalysis(); }); test("should return positive sentiment for positive text", () => { const result = sentimentAnalysis.getSentiment("I love this code and think it is great!"); expect(result).toEqual({ sentiment: "positive", positiveWords: 2, negativeWords: 0, neutralWords: 7 }); }); test("should return negative sentiment for negative text", () => { const result = sentimentAnalysis.getSentiment("I hate this code and think it is terrible!"); expect(result).toEqual({ sentiment: "negative", positiveWords: 0, negativeWords: 2, neutralWords: 7 }); }); test("should return neutral sentiment for neutral text", () => { const result = sentimentAnalysis.getSentiment("This code is just okay."); expect(result).toEqual({ sentiment: "neutral", positiveWords: 0, negativeWords: 0, neutralWords: 3 }); }); });
Our test cases are basic, but we check that we return the three different types of sentiment from our code. We aren’t handling invalid values or other edge cases you might have in a proper bunch of tests.