Things I learned while migrating to TypeScript

How do you feel about introducing new tools or technologies during development? I really enjoy introducing new technologies or tools. When I had been working at the company for about a year, I was fortunate enough to have the opportunity to migrate goormIDE to TypeScript. I fell in love with this project to the point where I was willing to work overtime. However, the project was stopped and the task soon became an ICE BOX (waiting due to low priority). This article is a memoir of that experience and a record of trial and error. I hope this article will be helpful to someone who will introduce TypeScript someday, or to me in the future.

💬 goormIDE is a cloud-based integrated development environment service. To put it simply, it is a tool that developers use to write code and develop, just like MS Word that we use to create documents. The biggest advantage of goormIDE is that rather than building a development environment directly on a PC, you can place the development environment in the cloud and access it through an Internet browser to develop in the same environment anywhere. In addition to the basic functions that can be used for free, various functions are provided as paid services. 

Why TypeScript?

First of all, I should tell you why I proposed introducing TypeScript into goormIDE. I didn’t start this simply because I wanted to use new technology. JavaScript is a dynamic language with loose typing. It is not type-dependent, so you can assign a value to any variable regardless of type whenever you use it. This feature helps make development fast and flexible. This feature, which is also an advantage, has led to several incidents(?) where problems have arisen. During this process, I realized that I was programming with the wrong type in mind.

😱 Incident 1 | Level 13 becomes level 13,100

It was the morning of April 1st, not long after the goormEXP homepage was created based on goormIDE (it happened to be April Fool’s Day).

When I tried to write a standup, my level was 13,100. (It was originally level 13.) It appeared to be a prank by goormEXP to commemorate April Fool’s Day, but in fact, this was a bug caused by loose typing, which is also an advantage of JavaScript. Originally, it was an event to add 100 to the level, but contrary to the intention, the existing level display was character data, so the number 100 was converted to character type and added. It was an unforgettable April Fool’s Day(?) event for goormee.

💬 goormEXP collects all the data that can be measured from clouds as much as possible and It is a system that quantifies and grants to clouds in the form of EXP (experience points).

💬 goormEXP’s stand-up organizes and shares what to do yesterday and what to do today so that everyone can do their best. It is a way to understand the work and confirm that we are moving in the same direction.
What is GoorumEXP and stand-up? ?

import PropTypes from 'prop-types';

class Greeting extends React.Component {
    render() {
        return (
            <h1>Hello, {this.props.name}</h1>
        );
    }
}

Greeting.propTypes = {
    name: PropTypes.string
};
JavaScript

To prevent problems caused by such loose typing, goormIDE uses a library called PropTypes. This library specifies the type of element that a React component receives from its parent in the code and checks it when executed. If an invalid type is entered, a warning is output to the console.

😱 Incident 2 | Endless type warning even if deleted

The click-up links in the following picture are the tasks I performed in the last week of the sprint to resolve various small bugs and warning messages. When performing this task, I had to correct the incorrect types provided by the PropTypes library described above. Over the course of about 15 weeks, I corrected the wrong type every 3 weeks. Even if it took 15 weeks to fix, the number of things that needed to be refreshed increased. 

During this process, we saw that the types were often incorrect and things may not work as expected by the developer. To improve the problem, I thought that TypeScript was needed to immediately display an error message when the type is incorrect. If the application does not work due to an error rather than a simple warning, people will pay more attention to type specifications.

Start migration alone

I wanted to solve the problem caused by loose typing. I thought that my team members would also feel this problem with JavaScript. First, I collected and studied several TypeScript migration articles to convince myself technically. The company was also considering introducing TypeScript as part of its technology goals for the year. So, I persuaded my team members to apply TypeScript to goormIDE. Although the team members were not opposed to introducing TypeScript, they were unsure about adopting it in the current project. So I decided to start by myself. If they see that product safety is improved by introducing TypeScript, they will be able to change their minds.

// tsconfig.json
/* JavaScript files are enabled in tsconfig */

...
       "allowJs": true,
       "skipLibCheck": true,
       "strict": false,
...

// eslintrc.client.js
/* eslint is also modified to use TypeScript concurrently */

...
overrides: [{
files: ['**/*.ts','**/*.tsx'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
...

The beginning was to create an environment where TypeScript and JavaScript could be used together. This is because it is impossible to change all the code of a large project at once. It was important to create an environment where both could be done in parallel. After creating the environment, I thought about applying it. I thought it would take a long time to design and consider all the parts, so I started with changing the number of data attributes with a small number.

export interface Container {
    always: boolean;
    authorId: string;
    collaborationSummary: {
        extraCollaboratorCount: number;
        representationCollaborators: Array<any>; // userInfo
        rootUserIds: Array<string>;
    };
    createDate: string;
    description: string;
    domains: Array<string>;
    gpu: boolean;
    imagingState: number;
    lastAccessDate: string;
    lastRunDate: string;
    lastStopDate: string;
    name: string;
    owner: UserInfo;
    portforward: Array<any>; // portInfo
    projectPath: string;
    shareLinkPermission: string;
    shareLinkType: string;
    spaceId?: string;
    stack: StackInfo;
    status: string;
    storageSize: number;
    terminalAccessLink: string;
    uid: string;
    workspaceAccessLink: string;
    customImageIndex?: string;
    launchingStep?: string;
    stopping?: boolean;
    alwaysOnDate?: Date;
    errCode?: any;
    stepCount?: number;
    creatingStep?: string;
}
JavaScript

😱 Incident 3 | Data with many components

After editing the data with few attributes, the next problem was. In order to change data with many properties, it was difficult to recognize the property type of all the data used there. I thought that by changing data with few properties first, I would be able to infer all types of data with many properties, but my expectation was wrong. Identifying and redefining the type of data with many properties required a lot of trial and error and time.

Also, when the type of data attribute that was written was used in other files, the type did not match, so there was a problem that it had to be rewritten. I was repeating the type error that occurred earlier. 

Another problem was that migration was not properly defined and designed. As a result, rather than modifying it while considering TypeScript, we often loaded the JavaScript file from the previous version of the migration to change the code safely and quickly.

What I learned from TypeScript migration

As the code I modified with TypeScript clashed with the JavaScript code, negative opinions about TypeScript increased within the team. As I am also busy with other urgent work, the introduction of TypeScript has been temporarily halted.

This incident made me realize two things. First, there must be sufficient design or preparation in order to transfer the technology. Because we wanted to apply it quickly, we neglected it, repeating the same mistakes and failing to take advantage of the technical advantages. Second, if you can’t convince the people who use it, it will cause more inconvenience than benefit. If it does not work properly, the benefits will not be achieved and may only cause more problems.

// JSDoc
/* A tool that aids in type inference in JavaScript. */
/** 

 * @param {string} name 
 * @param {string} phoneNumber 
 * @param {string} email 
 * @param {string} companyName 
 * @param {string} companyRegistrationNumber 
 * @param {{ 
 *  isEtc: boolean, 
 *  value: string, 
 *  etcDescription: string 
 * }} funnel 
 * @returns {Promise<boolean>} 
 */
JavaScript

I understand how important these two are, not only in migration but also in many other tasks, but design and persuasion are still difficult for me. So these days, I’m trying to document the work I’ve done and listen to my team members’ stories. Although the TypeScript migration failed, we took the time to find a tool that could check types in JavaScript and also shared a ‘challenge’ to help developers become familiar with TypeScript.

It seemed like I wasn’t the only one who learned something while taking on this challenge. As I was writing this, I searched and found that more people than I expected stopped at the Notion article that I wrote when I started using TypeScript. Many people have seen the article written when. I heard that some people referred to it when making presentations or decisions.

Looking back now, there were many shortcomings, but it was a good opportunity to be a good teacher to myself and to you all.

Posted by
mono.kim

I aspire to be a consistently reliable colleague, always striving to become a valuable asset in the development team.